├── glsl_fuzzer.cpp └── yacc_to_dict.cpp /glsl_fuzzer.cpp: -------------------------------------------------------------------------------- 1 | // anglefuzz.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 2 | #include "pch.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | //http://learnwebgl.brown37.net/12_shader_language/documents/_GLSL_ES_Specification_1.0.17.pdf 9 | 10 | enum define_proto_bytecount { 11 | PT_TYPE_IDENTIFIER = 0, //对应一个类型 12 | PT_VARIANT_NUM = 1, //取出第二个字符,0~255,拼接成a0~a255 13 | PT_ADDITIONAL_SIZE = 2, //如果大于0, 则给a初始化。一般有=和()两种形式,这个就不管了,直接原样读入后面的字符数。限制:32。 14 | PT_ADDITIONAL_DATA_START = 3, 15 | }; 16 | 17 | //any define could go here. 18 | std::string define_proto(unsigned char*& fuzzdata, int& remaining_size) { 19 | if (remaining_size < 3) 20 | return ""; 21 | 22 | remaining_size -= 3; 23 | 24 | int deftype = fuzzdata[PT_TYPE_IDENTIFIER]; 25 | int variant_num = fuzzdata[PT_VARIANT_NUM]; 26 | int additional_size = fuzzdata[PT_ADDITIONAL_SIZE]; 27 | fuzzdata += 3; 28 | if (remaining_size < additional_size) { 29 | return ""; 30 | } 31 | 32 | const char* presets[] = {"unsigned int", "signed int", 33 | "bool", "int", "uint" , "float", "bvec2", "bvec3", "bvec4", "ivec2", "ivec3", "ivec4", "uvec2", "uvce3", 34 | "uvec4", "vec2", "vec3", "vec4", "mat2" ,"mat3", "mat4", "mat2x3", "mat3x2", "mat2x4", "mat4x2", "mat3x4", 35 | "mat4x3" }; 36 | const char* type = presets[deftype % (sizeof(presets)/ sizeof(void*))]; 37 | char tmp[60] = { 0 }; 38 | snprintf(tmp, sizeof tmp, additional_size ? "%s a%d" : "%s a%d = ", type, variant_num); 39 | std::string out = tmp; 40 | if (additional_size) { 41 | char* additional_data = new char[additional_size + 1]; 42 | memset(additional_data, 0, additional_size + 1); 43 | memcpy(additional_data, fuzzdata, additional_size); 44 | out.append(additional_data); 45 | delete[] additional_data; 46 | 47 | fuzzdata += additional_size; 48 | remaining_size -= additional_size; 49 | } 50 | 51 | //out += ";\n"; no we are writing a proto we dont need to add ; here. 52 | return out; 53 | } 54 | 55 | 56 | enum define_variant_op { 57 | VO_VARIANT_NUM = 0, //0~255,拼接成a0~a255 58 | VO_OPERATE_TYPE = 1, //0: 数组, 1: .xxyy 类似这样的成员操作, 2: 一元操作, 3:直接读取fuzz数据(在左),4:直接读取fuzz(在右),5:不变 59 | VO_OPERATE_INDICATOR = 2, //如果是数组,则下标;如果是xxyy,则指定顺序;如果是一元操作,则代表正负、自增自减(在左或在右)、取反、取非;34则表明长度;5,直接原样返回 60 | VO_OPERATE_DATA = 3, 61 | }; 62 | enum const_define_variant_op { 63 | CONST_VO_OPERATE_TYPE_MAX = 5, 64 | CONST_VO_OPERATE_INDICATOR_UNARY_MAX = 11, 65 | 66 | }; 67 | 68 | std::string variant_op_proto(unsigned char*& fuzzdata, int& remaining_size) { 69 | if (remaining_size < 3) 70 | return ""; 71 | 72 | remaining_size -= 3; 73 | 74 | int variant_num = fuzzdata[VO_VARIANT_NUM]; 75 | int op_type = fuzzdata[VO_OPERATE_TYPE] % (CONST_VO_OPERATE_TYPE_MAX + 1); 76 | int op_indicator = fuzzdata[VO_OPERATE_INDICATOR]; 77 | 78 | const int buffer_size = 260; 79 | char* data_out = new char[buffer_size]; 80 | memset(data_out, 0, buffer_size); 81 | 82 | switch (op_type) { 83 | case 0: 84 | //array 85 | snprintf(data_out, buffer_size, "a%d[%d]", variant_num, op_indicator); //dont add space, use a seperate space switch case in main loop. 86 | fuzzdata += 3; 87 | break; 88 | case 1: 89 | //member op 90 | { 91 | char selective[17] = { 'r', 'g', 'b', 'a', 's', 't', 'p', 'q', 'w', 'x', 'y', 'z', '\0' }; 92 | if (remaining_size < 3){ 93 | fuzzdata += 3; 94 | delete[] data_out; 95 | 96 | return ""; 97 | } 98 | remaining_size -= 3; 99 | 100 | snprintf(data_out, buffer_size, "a%d.%c%c%c%c", variant_num, 101 | selective[op_indicator % sizeof(selective)], 102 | selective[fuzzdata[VO_OPERATE_INDICATOR + 1] % sizeof(selective)], 103 | selective[fuzzdata[VO_OPERATE_INDICATOR + 2] % sizeof(selective)], 104 | selective[fuzzdata[VO_OPERATE_INDICATOR + 3] % sizeof(selective)]); 105 | 106 | fuzzdata += 6; 107 | } 108 | break; 109 | case 2: 110 | //unary op 111 | switch(op_indicator % CONST_VO_OPERATE_INDICATOR_UNARY_MAX) { 112 | case 0: 113 | snprintf(data_out, buffer_size, "a%d++", variant_num); break; 114 | case 1: 115 | snprintf(data_out, buffer_size, "a%d--", variant_num); break; 116 | case 2: 117 | snprintf(data_out, buffer_size, "++a%d", variant_num); break; 118 | case 3: 119 | snprintf(data_out, buffer_size, "--a%d", variant_num); break; 120 | case 4: 121 | snprintf(data_out, buffer_size, "!a%d", variant_num); break; 122 | case 5: 123 | snprintf(data_out, buffer_size, "~a%d", variant_num); break; 124 | case 6: 125 | snprintf(data_out, buffer_size, "!!a%d", variant_num); break; 126 | case 7: 127 | snprintf(data_out, buffer_size, "!~a%d", variant_num); break; 128 | case 8: 129 | snprintf(data_out, buffer_size, "+a%d", variant_num); break; 130 | case 9: 131 | snprintf(data_out, buffer_size, "-a%d", variant_num); break; 132 | case 10: 133 | snprintf(data_out, buffer_size, "sizeof(a%d)", variant_num); break; 134 | default: 135 | snprintf(data_out, buffer_size, "ERROR!!a%d", variant_num); break; // shouldn't go here. 136 | } 137 | fuzzdata += 3; 138 | break; 139 | case 3: 140 | //left-reading fuzz data 141 | if (remaining_size < op_indicator){ 142 | fuzzdata += 3; 143 | delete[] data_out; 144 | 145 | return ""; 146 | } 147 | remaining_size -= op_indicator; 148 | memcpy(data_out, &fuzzdata[VO_OPERATE_DATA], op_indicator); //op indicator should be <= 255. we still have 5 bytes to use 149 | 150 | snprintf(&data_out[op_indicator], buffer_size - op_indicator, "a%d", variant_num); 151 | 152 | fuzzdata += 3; 153 | fuzzdata += op_indicator; 154 | break; 155 | case 4: 156 | //right-reading fuzz data 157 | if (remaining_size < op_indicator) { 158 | fuzzdata += 3; 159 | delete[] data_out; 160 | 161 | return ""; 162 | } 163 | remaining_size -= op_indicator; 164 | 165 | snprintf(data_out, buffer_size, "a%d", variant_num); 166 | 167 | memcpy(&data_out[strlen(data_out)], 168 | &fuzzdata[VO_OPERATE_DATA], op_indicator); 169 | fuzzdata += 3; 170 | fuzzdata += op_indicator; 171 | break; 172 | case 5: 173 | //keep original 174 | snprintf(data_out, buffer_size, "a%d", variant_num); 175 | fuzzdata += 3; 176 | break; 177 | default: 178 | fuzzdata += 3; 179 | break; 180 | } 181 | 182 | std::string p = data_out; 183 | delete[] data_out; 184 | return p; 185 | } 186 | 187 | enum define_binary_operator_op { 188 | BI_OPERATE_INDICATOR = 0, 189 | }; 190 | 191 | std::string binary_operator_proto(unsigned char*& fuzzdata, int& remaining_size) { 192 | if (remaining_size < 1) 193 | return ""; 194 | 195 | 196 | int variant_num = fuzzdata[BI_OPERATE_INDICATOR]; 197 | fuzzdata++; 198 | remaining_size -= 1; 199 | 200 | const char* arr_list[] = { 201 | "+", "-", "*", "/", "%", " defined " 202 | "&", "^", "|", ",", 203 | ">", "<", "%", "\\", "=" 204 | "||", "&&", ">>", "<<", "==", ">=", "<=", ">>=", "<<=", "%=" 205 | ".", "+=", "-=", "*=", "/=", "&=", "^=", "|=", "?", ":", 206 | "//", "/*", "*/" 207 | }; 208 | 209 | return arr_list[variant_num % (sizeof(arr_list) / sizeof(void*))]; 210 | } 211 | 212 | 213 | enum define_numeric_operator_op { 214 | NU_SIZE_INDICATOR = 0, 215 | NU_HEX_OCT_DEC = 1, 216 | }; 217 | 218 | std::string numeric_operator_proto(unsigned char*& fuzzdata, int& remaining_size) { 219 | if (remaining_size < 2) 220 | return ""; 221 | 222 | 223 | int num_size = fuzzdata[NU_SIZE_INDICATOR]; 224 | int num_type = fuzzdata[NU_HEX_OCT_DEC]; 225 | fuzzdata++; 226 | remaining_size -= 2; 227 | 228 | if (remaining_size < num_size) 229 | return "0"; 230 | std::string out; 231 | 232 | switch (num_type % 6) { 233 | case 0: 234 | out = "-"; break; 235 | case 1: 236 | out = "0x"; break; 237 | case 2: 238 | out = "0"; break; 239 | case 3: 240 | out = "-0x"; break; 241 | case 4: 242 | out = "-0"; break; 243 | case 5: default: 244 | break; 245 | } 246 | 247 | //leonwxqian: yes i know there shouldn't be "." in hex and "a" in dec and "8" in oct here .. 248 | // just trying to mess the things up. 249 | const char* arr_list_hex[] = { 250 | "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "." 251 | "a", "b", "c", "d", "e", "f" 252 | }; 253 | 254 | const char* arr_list_dec[] = { 255 | "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "." 256 | "a" 257 | }; 258 | 259 | const char* arr_list_oct[] = { 260 | "0", "1", "2", "3", "4", "5", "6", "7", "8" 261 | }; 262 | 263 | for (int i = 0; i < num_size; i++) { 264 | 265 | switch (num_type % 6) { 266 | case 1: case 3: 267 | out += arr_list_hex[fuzzdata[i] % (sizeof(arr_list_hex) / sizeof(void*))]; 268 | break; 269 | case 2: case 4: 270 | out += arr_list_oct[fuzzdata[i] % (sizeof(arr_list_oct) / sizeof(void*))]; 271 | break; 272 | case 0: case 5: default: 273 | out += arr_list_dec[fuzzdata[i] % (sizeof(arr_list_dec) / sizeof(void*))]; 274 | 275 | break; 276 | } 277 | 278 | } 279 | 280 | num_type /= 10; 281 | switch (num_type % 6) { 282 | case 0: 283 | out += "e+"; break; 284 | case 1: 285 | out += "e-"; break; 286 | case 2: 287 | out += "u"; break; 288 | case 3: 289 | out += "l"; break; 290 | case 4: 291 | out += "f"; break; 292 | case 5: default: 293 | out += "."; break; 294 | break; 295 | } 296 | 297 | 298 | 299 | fuzzdata += num_size; 300 | remaining_size -= num_size; 301 | 302 | return out; 303 | } 304 | 305 | enum define_type_op { 306 | TY_INDICATOR = 0, 307 | }; 308 | 309 | std::string get_typename_proto(unsigned char*& fuzzdata, int& remaining_size) { 310 | if (remaining_size < 1) 311 | return ""; 312 | 313 | remaining_size -= 1; 314 | int type_indicator = fuzzdata[TY_INDICATOR]; 315 | fuzzdata++; 316 | 317 | std::string out; 318 | 319 | const char* arr_list[] = { "signed", "unsigned", 320 | "bool ", "int", "uint" , "float", "bvec2", "bvec3", "bvec4", "ivec2", "ivec3", "ivec4", "uvec2", "uvce3", 321 | "uvec4", "vec2", "vec3", "vec4", "mat2" ,"mat3", "mat4", "mat2x3", "mat3x2", "mat2x4", "mat4x2", "mat3x4", 322 | "mat4x3" 323 | }; 324 | 325 | out += arr_list[type_indicator % (sizeof(arr_list) / sizeof(void*))]; 326 | out += " "; 327 | 328 | return out; 329 | } 330 | 331 | enum define_builtin_func_op { 332 | BF_INDICATOR = 0, 333 | }; 334 | std::string get_builtin_funcname_proto(unsigned char*& fuzzdata, int& remaining_size) { 335 | if (remaining_size < 1) 336 | return ""; 337 | 338 | remaining_size -= 1; 339 | int type_indicator = fuzzdata[BF_INDICATOR]; 340 | fuzzdata++; 341 | 342 | std::string out; 343 | 344 | const char* arr_list[] = { "abs", "acos", "acosh","asin","asinh","atan","atanh","ceil","clamp","cos","cosh","degrees","dFdx","dFdy","exp","exp2","faceforward", 345 | "floor","fract","fwidth","intBitsToFloat","uintBitsToFloat","inversesqrt","log","log2","max","min","mix","mod","normalize","pow","radians","reflect", 346 | "refract","round","roundEven","sign","sin","sinh","smoothstep","sqrt","step","tan","tanh","modf","trunc","distance","length","floatBitsToUint", 347 | "packHalf2x16","packUnorm2x16","packSnorm2x16","isinf","isnan","any","not","equal","greaterThan","lessThan","greaterThanEqual","lessThanEqual","notEqual", 348 | "inverse","matrixCompMult","outerProduct","transpose","cross","unpackHalf2x16","unpackUnorm2x16","unpackSnorm2x16"}; 349 | 350 | out += arr_list[type_indicator % (sizeof(arr_list) / sizeof(void*))]; 351 | out += " "; 352 | 353 | return out; 354 | } 355 | 356 | enum define_gen_func_op { //function use f0~255 as name 357 | GF_INDICATOR = 0, 358 | GF_INDICATOR2 = 1, 359 | 360 | }; 361 | 362 | std::string get_gen_funcname_proto(unsigned char*& fuzzdata, int& remaining_size) { 363 | if (remaining_size < 2) 364 | return ""; 365 | 366 | remaining_size -= 2; 367 | int type_indicator1 = fuzzdata[GF_INDICATOR]; 368 | int type_indicator2 = fuzzdata[GF_INDICATOR2]; 369 | int type_indicator = type_indicator1 << 8 + type_indicator2; 370 | fuzzdata += 2; 371 | 372 | std::string out; 373 | 374 | const char* arr_list[] = { "abs", "acos", "acosh","asin","asinh","atan","atanh","ceil","clamp","cos","cosh","degrees","dFdx","dFdy","exp","exp2","faceforward", 375 | "floor","fract","fwidth","intBitsToFloat","uintBitsToFloat","inversesqrt","log","log2","max","min","mix","mod","normalize","pow","radians","reflect", 376 | "refract","round","roundEven","sign","sin","sinh","smoothstep","sqrt","step","tan","tanh","modf","trunc","distance","length","floatBitsToUint", 377 | "packHalf2x16","packUnorm2x16","packSnorm2x16","isinf","isnan","any","not","equal","greaterThan","lessThan","greaterThanEqual","lessThanEqual","notEqual", 378 | "inverse","matrixCompMult","outerProduct","transpose","cross","unpackHalf2x16","unpackUnorm2x16","unpackSnorm2x16", 379 | "iadd","isub","imad","imul","rcpx","idiv","udiv","imod","umod","ishr","ushr","rsqx","sqrt","len2","len3","len4","dist1","dist2","dist3","dist4","det2","det3", 380 | "det4","imin","umin","imax","umax","exp2x","log2x","step","smooth","floatBitsToInt","floatBitsToUInt","intBitsToFloat","uintBitsToFloat","packSnorm2x16","packUnorm2x16", 381 | "packHalf2x16","unpackSnorm2x16","unpackUnorm2x16","unpackHalf2x16","m4x4","m4x3","m3x4","m3x3","m3x2","call","callnz","loop","endloop","label","powx","isgn","iabs","nrm2", 382 | "nrm3","nrm4","sincos","endrep","texcoord","texkill","discard","texld","texbem","texbeml","texreg2ar","texreg2gb","texm3x2pad","texm3x2tex","texm3x3pad", 383 | "texm3x3tex","reserved0","texm3x3spec","texm3x3vspec","expp","logp","texreg2rgb","texdp3tex","texm3x2depth","texdp3","texm3x3","texdepth","cmp0","icmp","ucmp", 384 | "select","extract","insert","dp2add","fwidth","texldd","texldl","texbias","texoffset","texoffsetbias","texlodoffset","texelfetch","texelfetchoffset","texgrad", 385 | "texgradoffset","breakp","texsize","phase","comment","ps_1_0","ps_1_1","ps_1_2","ps_1_3","ps_1_4","ps_2_0","ps_2_x","ps_3_0","vs_1_0","vs_1_1","vs_2_0", 386 | "vs_2_x","vs_2_sw","vs_3_0","vs_3_sw","atan2","sinh","tanh","acosh","trunc","floor","round","roundEven","ceil","exp2","log2","ineg","isnan","isinf","forward1", 387 | "forward2","forward3","forward4","reflect1","reflect2","reflect3","reflect4","refract1","refract2","refract3","refract4", 388 | }; 389 | 390 | 391 | out += arr_list[type_indicator % (sizeof(arr_list) / sizeof(void*))]; 392 | out += " "; 393 | 394 | return out; 395 | } 396 | 397 | enum text_insertion_op { //function use f0~255 as name 398 | TI_INDICATOR_OPS = 0, //多少操作 399 | TI_INDICATOR_DIRECTION = 1, //向前或向后 400 | TI_INDICATOR_OFFSET = 2, //偏移多少字节 (同时保留偏移) 401 | TI_INDICATOR_SIZE = 3, //插入多少字节 402 | }; 403 | 404 | std::string textinsertion_proto(unsigned char*& fuzzdata, int& remaining_size, const char* current_output) { 405 | static int offset = 0; /*维持一个全局计数器,默认从0开始*/ 406 | std::string in = current_output; 407 | std::string out; 408 | 409 | if (remaining_size < 4) 410 | return ""; 411 | int op_count = fuzzdata[TI_INDICATOR_OPS]; 412 | int op_direction = fuzzdata[TI_INDICATOR_DIRECTION] % 2 ? 1 : -1; 413 | int op_offset = fuzzdata[TI_INDICATOR_OFFSET]; 414 | int op_size = fuzzdata[TI_INDICATOR_OFFSET]; 415 | fuzzdata += 4; 416 | remaining_size -= 4; 417 | 418 | if (remaining_size < op_size || op_count == 0) 419 | return ""; 420 | 421 | int i = 0; 422 | 423 | do { 424 | offset += op_direction * op_offset; 425 | if (offset < 0) 426 | offset = 0; 427 | else if (offset > in.length()) 428 | offset = in.length(); 429 | 430 | char* data_to_insert = new char[op_size + 1]; 431 | memset(data_to_insert, 0, op_size + 1); 432 | memcpy(data_to_insert, fuzzdata, op_size); 433 | 434 | out = in.substr(0, offset); 435 | out += data_to_insert; 436 | out += in.substr(offset); 437 | 438 | delete[]data_to_insert; 439 | in = out; 440 | 441 | fuzzdata += op_size; 442 | remaining_size -= op_size; 443 | 444 | if (remaining_size < 3) 445 | return out; 446 | 447 | op_direction = fuzzdata[TI_INDICATOR_DIRECTION] % 2 ? 1 : -1; 448 | op_offset = fuzzdata[TI_INDICATOR_OFFSET]; 449 | op_size = fuzzdata[TI_INDICATOR_OFFSET]; 450 | 451 | fuzzdata += 3; 452 | remaining_size -= 3; 453 | 454 | if (remaining_size < op_size) 455 | break; 456 | 457 | i++; 458 | } while (i < op_count); 459 | 460 | return out; 461 | 462 | } 463 | 464 | /* 465 | enum switch_op { 466 | //read switch what from input. 467 | //add cases from input too. 468 | //add processing data from input too. 469 | //this is not a primitive 470 | }; 471 | enum for_op { 472 | //this is not a primitive 473 | }; 474 | enum while_op { 475 | //this is not a primitive 476 | }; 477 | */ 478 | 479 | //用Prewords来替换之前的for/while/switch之类的,用于简化 480 | enum prewords_available_op { 481 | PA_INDICATOR = 0, 482 | }; 483 | 484 | std::string prewords_available_proto(unsigned char*& fuzzdata, int& remaining_size) { 485 | if (remaining_size < 1) 486 | return ""; 487 | 488 | int type_indicator = fuzzdata[PA_INDICATOR]; 489 | fuzzdata += 1; 490 | remaining_size -= 1; 491 | 492 | 493 | std::string out; 494 | 495 | const char* arr_list[] = { 496 | //already-have: 497 | "attribute","const","uniform","varying","break;","continue;","do{","for(","while(", 498 | "if(","else","in","out","inout","void","true","false","lowp","mediump","highp","precision","invariant" 499 | "discard","return","struct", 500 | 501 | "signed", "unsigned", 502 | "bool ", "int", "uint", "float", "bvec2", "bvec3", "bvec4", "ivec2", "ivec3", "ivec4", "uvec2", "uvce3", 503 | "uvec4", "vec2", "vec3", "vec4", "mat2", "mat3", "mat4", "mat2x3", "mat3x2", "mat2x4", "mat4x2", "mat3x4", 504 | "mat4x3" 505 | 506 | // yeah we might also want to try int(int) like this. 507 | }; 508 | 509 | out += arr_list[type_indicator % ((sizeof(arr_list) / sizeof(void*)) / sizeof(void*))]; 510 | out += " "; 511 | 512 | return out; 513 | } 514 | 515 | enum prewords_navailable_op { 516 | PN_INDICATOR = 0, 517 | }; 518 | 519 | std::string prewords_navailable_proto(unsigned char*& fuzzdata, int& remaining_size) { 520 | if (remaining_size < 1) 521 | return ""; 522 | 523 | int type_indicator = fuzzdata[PN_INDICATOR]; 524 | fuzzdata += 1; 525 | remaining_size -= 1; 526 | 527 | 528 | std::string out; 529 | 530 | const char* arr_list[] = { 531 | 532 | //preserved: 533 | "asm","class","union","enum","typedef","template","this","packed", "goto","switch","default","inline", 534 | "noinline","volatile","public","static","extern","external","interface","flat","sampler2D","samplerCube" 535 | 536 | 537 | }; 538 | 539 | out += arr_list[type_indicator % (sizeof(arr_list) / sizeof(void*))]; 540 | out += " "; 541 | 542 | return out; 543 | } 544 | 545 | enum pragma_op { 546 | PM_INDICATOR = 0, 547 | PM_INDICATOR2 = 1, //optional 548 | PM_INDICATOR3_EXT_NAME = 2, //optional 549 | }; 550 | 551 | std::string pragma_proto(unsigned char*& fuzzdata, int& remaining_size) { 552 | if (remaining_size < 1) 553 | return ""; 554 | 555 | int type_indicator = fuzzdata[PM_INDICATOR]; 556 | fuzzdata++; 557 | remaining_size -= 1; 558 | 559 | std::string out; 560 | 561 | const char* arr_list[] = { "#", "#define", "#undef", "#if", "#ifdef", "#ifndef", "#else" ,"#elif", "#endif", 562 | "#error", "#pragma", "#extension", "#version", "#line" 563 | }; 564 | 565 | out += arr_list[type_indicator % (sizeof(arr_list) / sizeof(void*))]; 566 | 567 | if (out == "#pragma") { 568 | if (remaining_size < 1) 569 | return out; 570 | int type_indicator2 = fuzzdata[0]; //because the fuzzdata is already moved, so we can't do too much here. 571 | fuzzdata++; 572 | remaining_size -= 1; 573 | 574 | if (type_indicator2 % 2) 575 | out += " optimize"; 576 | else 577 | out += " debug"; 578 | 579 | type_indicator2 /= 10; 580 | 581 | if (type_indicator2 % 2) 582 | out += "(on)"; 583 | else 584 | out += "(off)"; 585 | } 586 | else if (out == "#version") { 587 | if (remaining_size < 1) 588 | return out; 589 | int type_indicator2 = fuzzdata[0]; //0~255. 590 | fuzzdata++; 591 | remaining_size -= 1; 592 | 593 | char sztmp[6] = {0}; 594 | snprintf(sztmp, 6, " %3d0", type_indicator2); //version is a number grouped by times of 10 595 | out += sztmp; 596 | } 597 | else if (out == "#extension") { 598 | if (remaining_size < 1) 599 | return out; 600 | int type_indicator2 = fuzzdata[0]; 601 | int exttype = type_indicator2 % 2; // 0~1 602 | type_indicator2 /= 10; 603 | int extbehaviour = type_indicator2 % 4; // 0~3 604 | fuzzdata++; 605 | remaining_size -= 1; 606 | 607 | if (exttype) { 608 | out += " all : "; 609 | } 610 | else { 611 | if (remaining_size < 1) 612 | return out; 613 | int extlen = fuzzdata[0]; 614 | fuzzdata++; 615 | remaining_size--; 616 | 617 | if (remaining_size < extlen) 618 | return out; 619 | char* tmp = new char[extlen + 1]; 620 | memset(tmp, 0, extlen + 1); 621 | memcpy(tmp, &fuzzdata[0], extlen); 622 | out += tmp; 623 | delete[] tmp; 624 | out += " : "; 625 | 626 | fuzzdata += extlen; 627 | remaining_size -= extlen; 628 | } 629 | 630 | switch (extbehaviour) { 631 | case 0: 632 | out += "require\n"; 633 | break; 634 | case 1: 635 | out += "enable\n"; 636 | break; 637 | case 2: 638 | out += "warn\n"; 639 | break; 640 | case 3: 641 | default: 642 | out += "disable\n"; 643 | break; 644 | } 645 | 646 | } 647 | out += " "; 648 | 649 | return out; 650 | } 651 | 652 | enum quote_insertion_op { 653 | //this is a primitive 654 | QI_INDICATOR = 0, 655 | }; 656 | 657 | std::string quote_insertion_proto(unsigned char*& fuzzdata, int& remaining_size) { 658 | if (remaining_size < 1) 659 | return ""; 660 | 661 | int type_indicator = fuzzdata[QI_INDICATOR]; 662 | fuzzdata += 1; 663 | remaining_size -= 1; 664 | 665 | 666 | std::string out; 667 | 668 | const char* arr_list[] = { 669 | ";", "{", "}", "(", ")", "[", "]", ",", "\n", "\r", "\t" 670 | }; 671 | 672 | out += arr_list[type_indicator % (sizeof(arr_list) / sizeof(void*))]; 673 | out += " "; 674 | 675 | return out; 676 | } 677 | 678 | 679 | enum predefined_op { 680 | PD_INDICATOR = 0, 681 | }; 682 | 683 | std::string predefined_insertion_proto(unsigned char*& fuzzdata, int& remaining_size) { 684 | if (remaining_size < 1) 685 | return ""; 686 | 687 | int type_indicator = fuzzdata[PD_INDICATOR]; 688 | fuzzdata += 1; 689 | remaining_size -= 1; 690 | 691 | 692 | std::string out; 693 | 694 | const char* arr_list[] = { 695 | "__LINE__", "__FILE__", "__VERSION__", "GL_ES", "gl_Position" , "gl_PointSize", "gl_FragColor", "gl_FragData", "gl_FragCoord" 696 | 697 | }; 698 | 699 | out += arr_list[type_indicator % (sizeof(arr_list) / sizeof(void*))]; 700 | out += " "; 701 | 702 | return out; 703 | } 704 | 705 | 706 | enum raw_data_op { 707 | RD_INDICATOR = 0, 708 | }; 709 | 710 | std::string raw_data_proto(unsigned char*& fuzzdata, int& remaining_size) { 711 | if (remaining_size < 1) 712 | return ""; 713 | 714 | int rawdata_size = fuzzdata[RD_INDICATOR]; 715 | fuzzdata += 1; 716 | remaining_size -= 1; 717 | 718 | if (remaining_size < rawdata_size) 719 | return ""; 720 | 721 | std::string out; 722 | 723 | char* data = new char[rawdata_size + 1]; 724 | memset(data, 0, rawdata_size + 1); 725 | memcpy(data, fuzzdata, rawdata_size); 726 | out += data; 727 | delete[] data; 728 | 729 | fuzzdata += rawdata_size; 730 | remaining_size -= rawdata_size; 731 | 732 | return out; 733 | } 734 | 735 | 736 | 737 | enum qualifier_op { 738 | QF_INDICATOR = 0, 739 | }; 740 | 741 | std::string qualifier_proto(unsigned char*& fuzzdata, int& remaining_size) { 742 | if (remaining_size < 1) 743 | return ""; 744 | 745 | int type = fuzzdata[QF_INDICATOR]; 746 | 747 | fuzzdata += 1; 748 | remaining_size -= 1; 749 | std::string out; 750 | 751 | switch (type % 7) { 752 | case 0: 753 | out = "layout(location ="; 754 | out += numeric_operator_proto(fuzzdata, remaining_size); 755 | out += ") "; 756 | break; 757 | case 1: 758 | out = "layout(stream ="; 759 | out += numeric_operator_proto(fuzzdata, remaining_size); 760 | out += ") "; 761 | break; 762 | case 2: 763 | out = "layout(std430, binding = "; 764 | out += numeric_operator_proto(fuzzdata, remaining_size); 765 | out += ") "; 766 | break; 767 | case 3: 768 | out = "layout(xfb_buffer ="; 769 | out += numeric_operator_proto(fuzzdata, remaining_size); 770 | out += ") "; 771 | break; 772 | case 4: 773 | out = "layout(xfb_buffer ="; 774 | out += numeric_operator_proto(fuzzdata, remaining_size); 775 | out = ", xfb_stride ="; 776 | out += numeric_operator_proto(fuzzdata, remaining_size); 777 | out += ") "; 778 | break; 779 | case 5: 780 | out = "layout(origin_upper_left) "; break; 781 | case 6: 782 | default: 783 | out = "layout(index = "; 784 | out += numeric_operator_proto(fuzzdata, remaining_size); 785 | out += ") "; 786 | break; 787 | 788 | } 789 | 790 | return out; 791 | } 792 | 793 | enum struct_op { 794 | ST_INDICATOR = 0, 795 | }; 796 | 797 | std::string gen_struct_proto(unsigned char*& fuzzdata, int& remaining_size) { 798 | if (remaining_size < 1) 799 | return ""; 800 | 801 | int member_count = fuzzdata[ST_INDICATOR]; 802 | 803 | fuzzdata += 1; 804 | remaining_size -= 1; 805 | std::string out = "struct a"; 806 | if (member_count > 127) { 807 | out = "union a"; 808 | } 809 | 810 | out += std::to_string(member_count); 811 | out += "{\n"; 812 | 813 | for(int i = 0; i < member_count; i++) { 814 | out += define_proto(fuzzdata, remaining_size); 815 | out += ";\n"; 816 | } 817 | out += "};\n"; 818 | return out; 819 | } 820 | 821 | 822 | 823 | enum arr_query_op { 824 | AR_INDICATOR = 0, 825 | }; 826 | 827 | std::string gen_arrquery_proto(unsigned char*& fuzzdata, int& remaining_size) { 828 | if (remaining_size < 1) 829 | return ""; 830 | 831 | int arr_idx = fuzzdata[AR_INDICATOR]; 832 | 833 | fuzzdata += 1; 834 | remaining_size -= 1; 835 | std::string out = "["; 836 | out += std::to_string(arr_idx); 837 | out += "]"; 838 | 839 | return out; 840 | } 841 | 842 | enum function_define_op { 843 | FD_RET_TYPE = 0, //返回值 844 | FD_FNAME = 1, //函数名 845 | FD_ARG_COUNT = 2, //参数数量 846 | /* 847 | FD_ARG1_TYPE = 3, 848 | FD_ARG2_TYPE = 4, 849 | ... 850 | */ 851 | }; 852 | 853 | std::string function_define_proto(unsigned char*& fuzzdata, int& remaining_size) { 854 | if (remaining_size < 3) 855 | return ""; 856 | 857 | int func_ret_type = fuzzdata[FD_RET_TYPE]; 858 | int func_name = fuzzdata[FD_FNAME]; 859 | int arg_count = fuzzdata[FD_ARG_COUNT]; 860 | fuzzdata += 3; 861 | remaining_size -= 3; 862 | 863 | 864 | std::string out; 865 | 866 | const char* type_list_func[] = { "void","bool", "int", "uint" , "float", "bvec2", "bvec3", "bvec4", "ivec2", "ivec3", "ivec4", "uvec2", "uvce3", 867 | "uvec4", "vec2", "vec3", "vec4", "mat2" ,"mat3", "mat4", "mat2x3", "mat3x2", "mat2x4", "mat4x2", "mat3x4", 868 | "mat4x3" }; 869 | const char* type_list_arg[] = { "bool", "int", "uint" , "float", "bvec2", "bvec3", "bvec4", "ivec2", "ivec3", "ivec4", "uvec2", "uvce3", 870 | "uvec4", "vec2", "vec3", "vec4", "mat2" ,"mat3", "mat4", "mat2x3", "mat3x2", "mat2x4", "mat4x2", "mat3x4", 871 | "mat4x3" }; //remove bool. 872 | 873 | out += type_list_func[func_ret_type % (sizeof(type_list_func) / sizeof(void*))]; 874 | out += " a"; //int aXX( 875 | out += std::to_string(func_name); 876 | out += "("; 877 | 878 | for (int i = 0; i < arg_count; i++) { 879 | if (remaining_size < 1) 880 | return out; 881 | int arg_ret_type = fuzzdata[0]; 882 | 883 | out += type_list_arg[arg_ret_type % (sizeof(type_list_arg) / sizeof(void*))]; 884 | out += " a"; //int_ 885 | out += std::to_string(i); 886 | if (i != arg_count - 1) 887 | out += ","; 888 | 889 | remaining_size--; 890 | fuzzdata++; 891 | } 892 | 893 | out += "){\n"; //int aXX(int a0, bool b0, xxx c0){ 894 | 895 | out += "return "; 896 | return out; 897 | } 898 | 899 | 900 | enum for_while_define_op { 901 | FW_FOR_WHILE_OR_DO = 0, 902 | FW_START = 1, //起始值 903 | FW_END_VALUE = 2, //中止值 904 | FW_STEP_VALUE = 3, //步进 905 | }; 906 | std::string loop_proto(unsigned char*& fuzzdata, int& remaining_size) { 907 | if (remaining_size < 4) 908 | return ""; 909 | 910 | int for_while_do = fuzzdata[FW_FOR_WHILE_OR_DO]; 911 | int startvalue = fuzzdata[FW_START]; 912 | int endvalue = fuzzdata[FW_END_VALUE]; 913 | int stepvalue = fuzzdata[FW_STEP_VALUE]; 914 | fuzzdata += 4; 915 | remaining_size -= 4; 916 | 917 | 918 | std::string out; 919 | 920 | if (for_while_do % 3 == 0) { //for 921 | out = "for (int a255 = "; 922 | out += std::to_string(startvalue > 127 ? -1 * (startvalue - 127) : startvalue); 923 | out += "; a255 < "; 924 | out += std::to_string(endvalue > 127 ? -1 * (endvalue - 127) : endvalue); 925 | out += "; a255 += "; 926 | out += std::to_string(stepvalue > 127 ? -1 * (stepvalue - 127) : stepvalue); 927 | out += "){\n"; 928 | } 929 | else if (for_while_do % 3 == 1) { 930 | out = "int a255("; 931 | out += std::to_string(startvalue > 127 ? -1 * (startvalue - 127) : startvalue); 932 | out += ";\nwhile (a255 <"; 933 | out += std::to_string(endvalue > 127 ? -1 * (endvalue - 127) : endvalue); 934 | out += "){\n"; 935 | out += "a255 += "; 936 | out += std::to_string(stepvalue > 127 ? -1 * (stepvalue - 127) : stepvalue); 937 | out += ";\n"; 938 | } 939 | else if (for_while_do % 3 == 2) { 940 | out = "int a255("; 941 | out += std::to_string(startvalue > 127 ? -1 * (startvalue - 127) : startvalue); 942 | out += ";\ndo{"; 943 | out += "a255 += "; 944 | out += std::to_string(stepvalue > 127 ? -1 * (stepvalue - 127) : stepvalue); 945 | out += ";\n}while (a255 <"; 946 | out += std::to_string(endvalue > 127 ? -1 * (endvalue - 127) : endvalue); 947 | out += ");\n"; 948 | } 949 | return out; 950 | 951 | } 952 | 953 | 954 | int main() 955 | { 956 | unsigned char* data = (unsigned char*) "agn\x9e\x8o\x11noiwenyoiwnepymw"; 957 | int len = strlen((const char*)data); 958 | std::string out; 959 | 960 | while (len) { 961 | //we want a weighted result, so don't use switch.. 962 | 963 | unsigned char ch = data[0]; 964 | data++; 965 | len--; 966 | 967 | if (ch >= 0 && ch < 30) 968 | out += quote_insertion_proto(data, len); 969 | else if (ch >= 30 && ch < 40) 970 | out += predefined_insertion_proto(data, len); 971 | else if (ch >= 40 && ch < 50) 972 | out += pragma_proto(data, len); 973 | else if (ch >= 50 && ch < 53) 974 | out += prewords_navailable_proto(data, len); 975 | else if (ch >= 53 && ch < 70) 976 | out += prewords_available_proto(data, len); 977 | else if (ch >= 70 && ch < 80) 978 | out += get_builtin_funcname_proto(data, len); 979 | else if (ch >= 80 && ch < 90) 980 | out = textinsertion_proto(data, len, out.c_str()); //yes assign. 981 | else if (ch >= 90 && ch < 100) 982 | out += get_gen_funcname_proto(data, len); //general func name 983 | else if (ch >= 100 && ch < 110) 984 | out += get_typename_proto(data, len); 985 | else if (ch >= 110 && ch < 120) 986 | out += numeric_operator_proto(data, len); 987 | else if (ch >= 120 && ch < 130) 988 | out += binary_operator_proto(data, len); 989 | else if (ch >= 130 && ch < 140) 990 | out += variant_op_proto(data, len); 991 | else if (ch >= 140 && ch < 150) 992 | out += define_proto(data, len); 993 | else if (ch >= 150 && ch < 160) 994 | out += qualifier_proto(data ,len); 995 | else if (ch >= 160 && ch < 170) 996 | out += gen_arrquery_proto(data, len); 997 | else if (ch >= 180 && ch < 190) 998 | out += gen_struct_proto(data, len); 999 | else if (ch >= 190 && ch < 200) 1000 | out += function_define_proto(data, len); 1001 | else 1002 | out += raw_data_proto(data, len); 1003 | 1004 | out += " "; 1005 | } 1006 | 1007 | int n = out.size(); 1008 | int m = out.length(); 1009 | std::cout << out; 1010 | 1011 | return 0; 1012 | } 1013 | -------------------------------------------------------------------------------- /yacc_to_dict.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "pch.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | int help() { 14 | std::cout << 15 | R"( 16 | Usage: yacc_parser.exe PATH_TO_Y_FILE 17 | 18 | Also, please put binary `yacc` in the same folder with me. 19 | 20 | Please, compile yacc from the source file. 21 | )"; 22 | return -1; 23 | } 24 | 25 | int error() { 26 | std::cout << 27 | R"( 28 | ERROR 29 | 30 | Please check ther version of your ./yacc. A tested version is: yacc - 1.9 31 | )"; 32 | return -2; 33 | } 34 | 35 | int main(int argc, const char* argv[]) 36 | { 37 | if (argc == 1) 38 | return help(); 39 | 40 | const char* fn = argv[1]; 41 | std::string cmd("./yacc -r -o output "); 42 | cmd += fn; 43 | system(cmd.c_str()); //WARNING: THERE MIGHT BE A COMMAND INJECTION RISK HERE, USE IT LOCALLY AND BY YOURSELF ONLY. 44 | 45 | std::ifstream t(R"(./output)"); 46 | std::string str((std::istreambuf_iterator(t)), 47 | std::istreambuf_iterator()); 48 | t.close(); 49 | 50 | std::string tofind1 = "const char *const yyname[] = {"; 51 | std::string tofind2 = "};\nconst char *const yyrule[] = {"; 52 | int location1 = str.find(tofind1); 53 | int location2 = str.find(tofind2); 54 | if (location1 == std::string::npos || location2 == std::string::npos || location2 <= location1 + tofind1.length()) { 55 | return error(); 56 | } 57 | 58 | std::vector keywords; 59 | std::string data = str.substr(location1 + tofind1.length(), location2 - location1 - tofind1.length()); 60 | bool is_token = false; 61 | bool is_string = false; 62 | bool is_escapechar = false; 63 | std::string token; 64 | 65 | int i = 0; 66 | while (isspace(data.at(i))) //jumps off the initial spaces 67 | i++; 68 | 69 | for (; i < data.size(); i++) { 70 | if (data.at(i) == '\"' && !is_escapechar && !is_token && !is_string) { //1. not a token; 2. not \"; 3.not in str, ex: ["]66", 0, 71 | is_token = true; 72 | is_escapechar = false; 73 | 74 | continue; 75 | } 76 | if (data.at(i) == '\"' && !is_escapechar && is_token && !is_string) { //1. in token; 2. not \"; 3.not in str, ex: "66["], 0, 77 | is_token = false; //terminates the token scanning 78 | is_escapechar = false; 79 | 80 | keywords.push_back(token); 81 | token = ""; //push the data into keywords and continue. 82 | 83 | continue; 84 | } 85 | else if (data.at(i) == '\"' && !is_escapechar && is_token && is_string) { //1. not \"; 2. inside a token; 3. inside a string. Example: "'["]'" 86 | is_escapechar = false; 87 | 88 | continue; 89 | } 90 | else if (data.at(i) == '\"' && !is_escapechar && is_token) { //1. not \"; 2. inside a token; 3. outside a string. Example: "'c'["] 91 | is_token = false; 92 | is_escapechar = false; 93 | //TODO: add token to keywords 94 | continue; 95 | } 96 | else if (data.at(i) == '\\' && is_escapechar) { 97 | is_escapechar = false; 98 | token += '\\'; 99 | continue; 100 | } 101 | else if (data.at(i) == '\\' && !is_escapechar) { 102 | is_escapechar = true; 103 | token += '\\'; 104 | continue; 105 | } 106 | else if (i + 1 < data.size() && data.at(i) == '0' && data.at(i + 1) == ',') { // [0,] 0, 0, in yyname is just an empty placeholder, ignore them. 107 | i++; 108 | is_escapechar = false; 109 | 110 | continue; 111 | } 112 | else if (data.at(i) == '\'' && is_token && !is_escapechar && !is_string) { //1. inside a token; 2. not \'; 3. the first ', ex: "[']2'" 113 | is_string = true; 114 | is_escapechar = false; 115 | continue; 116 | } 117 | else if (data.at(i) == '\'' && is_token && !is_escapechar && is_string) { //1. inside a token; 2. not \'; 3. the last ', ex: "'2[']" 118 | is_string = false; 119 | is_escapechar = false; 120 | continue; 121 | } 122 | if (!is_token && !is_escapechar && !is_string) { 123 | continue; 124 | } 125 | is_escapechar = false; 126 | token += data.at(i); 127 | } 128 | 129 | std::cout << "Found these words: \n"; 130 | std::ostringstream stream; 131 | std::string dict = "\""; 132 | std::copy(keywords.begin(), keywords.end(), std::ostream_iterator(stream, "\"\n\"")); 133 | dict += stream.str(); 134 | dict.pop_back(); //remove the last junky \" 135 | 136 | std::cout << dict; 137 | 138 | std::ofstream out("dict"); 139 | out << dict; 140 | out.close(); 141 | 142 | std::cout << "\n----\n Strings listed above has been written to `dict`. \n"; 143 | return 0; 144 | } 145 | --------------------------------------------------------------------------------