1 /* 2 * Copyright 2016, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <cmath> 18 #include <random> 19 20 #include <inttypes.h> 21 #include <stdlib.h> 22 #include <stdio.h> 23 #include <string.h> 24 #include <unistd.h> 25 26 #include <sys/time.h> 27 28 namespace { 29 30 /* 31 * Operators. 32 */ 33 34 #define EMIT(x) fputs((x)[random0(sizeof(x)/sizeof(const char*))], out_); 35 36 static constexpr const char* kIncDecOps[] = { "++", "--" }; 37 static constexpr const char* kIntUnaryOps[] = { "+", "-", "~" }; 38 static constexpr const char* kFpUnaryOps[] = { "+", "-" }; 39 40 static constexpr const char* kBoolBinOps[] = { "&&", "||", "&", "|", "^" }; // few less common 41 static constexpr const char* kIntBinOps[] = { "+", "-", "*", "/", "%", 42 ">>", ">>>", "<<", "&", "|", "^" }; 43 static constexpr const char* kFpBinOps[] = { "+", "-", "*", "/" }; 44 45 static constexpr const char* kBoolAssignOps[] = { "=", "&=" , "|=", "^=" }; // few less common 46 static constexpr const char* kIntAssignOps[] = { "=", "+=", "-=", "*=", "/=", "%=", 47 ">>=", ">>>=", "<<=", "&=", "|=", "^=" }; 48 static constexpr const char* kFpAssignOps[] = { "=", "+=", "-=", "*=", "/=" }; 49 50 static constexpr const char* kBoolRelOps[] = { "==", "!=" }; 51 static constexpr const char* kRelOps[] = { "==", "!=", ">", ">=", "<", "<=" }; 52 53 /* 54 * Version of JFuzz. Increase this each time changes are made to the program 55 * to preserve the property that a given version of JFuzz yields the same 56 * fuzzed program for a deterministic random seed. 57 */ 58 const char* VERSION = "1.3"; 59 60 /* 61 * Maximum number of array dimensions, together with corresponding maximum size 62 * within each dimension (to keep memory/runtime requirements roughly the same). 63 */ 64 static const uint32_t kMaxDim = 10; 65 static const uint32_t kMaxDimSize[kMaxDim + 1] = { 0, 1000, 32, 10, 6, 4, 3, 3, 2, 2, 2 }; 66 67 /** 68 * A class that generates a random program that compiles correctly. The program 69 * is generated using rules that generate various programming constructs. Each rule 70 * has a fixed probability to "fire". Running a generated program yields deterministic 71 * output, making it suited to test various modes of execution (e.g an interpreter vs. 72 * an compiler or two different run times) for divergences. 73 */ 74 class JFuzz { 75 public: 76 JFuzz(FILE* out, 77 uint32_t seed, 78 uint32_t expr_depth, 79 uint32_t stmt_length, 80 uint32_t if_nest, 81 uint32_t loop_nest) 82 : out_(out), 83 fuzz_random_engine_(seed), 84 fuzz_seed_(seed), 85 fuzz_expr_depth_(expr_depth), 86 fuzz_stmt_length_(stmt_length), 87 fuzz_if_nest_(if_nest), 88 fuzz_loop_nest_(loop_nest), 89 return_type_(randomType()), 90 array_type_(randomType()), 91 array_dim_(random1(kMaxDim)), 92 array_size_(random1(kMaxDimSize[array_dim_])), 93 indentation_(0), 94 expr_depth_(0), 95 stmt_length_(0), 96 if_nest_(0), 97 loop_nest_(0), 98 switch_nest_(0), 99 do_nest_(0), 100 boolean_local_(0), 101 int_local_(0), 102 long_local_(0), 103 float_local_(0), 104 double_local_(0), 105 in_inner_(false) { } 106 107 ~JFuzz() { } 108 109 void emitProgram() { 110 emitHeader(); 111 emitTestClassWithMain(); 112 } 113 114 private: 115 // 116 // Types. 117 // 118 119 // Current type of each expression during generation. 120 enum Type { 121 kBoolean, 122 kInt, 123 kLong, 124 kFloat, 125 kDouble 126 }; 127 128 // Test for an integral type. 129 static bool isInteger(Type tp) { 130 return tp == kInt || tp == kLong; 131 } 132 133 // Test for a floating-point type. 134 static bool isFP(Type tp) { 135 return tp == kFloat || tp == kDouble; 136 } 137 138 // Emit type. 139 void emitType(Type tp) const { 140 switch (tp) { 141 case kBoolean: fputs("boolean", out_); break; 142 case kInt: fputs("int", out_); break; 143 case kLong: fputs("long", out_); break; 144 case kFloat: fputs("float", out_); break; 145 case kDouble: fputs("double", out_); break; 146 } 147 } 148 149 // Emit type class. 150 void emitTypeClass(Type tp) const { 151 switch (tp) { 152 case kBoolean: fputs("Boolean", out_); break; 153 case kInt: fputs("Integer", out_); break; 154 case kLong: fputs("Long", out_); break; 155 case kFloat: fputs("Float", out_); break; 156 case kDouble: fputs("Double", out_); break; 157 } 158 } 159 160 // Return a random type. 161 Type randomType() { 162 switch (random1(5)) { 163 case 1: return kBoolean; 164 case 2: return kInt; 165 case 3: return kLong; 166 case 4: return kFloat; 167 default: return kDouble; 168 } 169 } 170 171 // 172 // Expressions. 173 // 174 175 // Emit an unary operator (same type in-out). 176 void emitUnaryOp(Type tp) { 177 if (tp == kBoolean) { 178 fputc('!', out_); 179 } else if (isInteger(tp)) { 180 EMIT(kIntUnaryOps); 181 } else { // isFP(tp) 182 EMIT(kFpUnaryOps); 183 } 184 } 185 186 // Emit a pre/post-increment/decrement operator (same type in-out). 187 void emitIncDecOp(Type tp) { 188 if (tp == kBoolean) { 189 // Not applicable, just leave "as is". 190 } else { // isInteger(tp) || isFP(tp) 191 EMIT(kIncDecOps); 192 } 193 } 194 195 // Emit a binary operator (same type in-out). 196 void emitBinaryOp(Type tp) { 197 if (tp == kBoolean) { 198 EMIT(kBoolBinOps); 199 } else if (isInteger(tp)) { 200 EMIT(kIntBinOps); 201 } else { // isFP(tp) 202 EMIT(kFpBinOps); 203 } 204 } 205 206 // Emit an assignment operator (same type in-out). 207 void emitAssignmentOp(Type tp) { 208 if (tp == kBoolean) { 209 EMIT(kBoolAssignOps); 210 } else if (isInteger(tp)) { 211 EMIT(kIntAssignOps); 212 } else { // isFP(tp) 213 EMIT(kFpAssignOps); 214 } 215 } 216 217 // Emit a relational operator (one type in, boolean out). 218 void emitRelationalOp(Type tp) { 219 if (tp == kBoolean) { 220 EMIT(kBoolRelOps); 221 } else { // isInteger(tp) || isFP(tp) 222 EMIT(kRelOps); 223 } 224 } 225 226 // Emit a type conversion operator sequence (out type given, new suitable in type picked). 227 Type emitTypeConversionOp(Type tp) { 228 if (tp == kInt) { 229 switch (random1(5)) { 230 case 1: fputs("(int)", out_); return kLong; 231 case 2: fputs("(int)", out_); return kFloat; 232 case 3: fputs("(int)", out_); return kDouble; 233 // Narrowing-widening. 234 case 4: fputs("(int)(byte)(int)", out_); return kInt; 235 case 5: fputs("(int)(short)(int)", out_); return kInt; 236 } 237 } else if (tp == kLong) { 238 switch (random1(6)) { 239 case 1: /* implicit */ return kInt; 240 case 2: fputs("(long)", out_); return kFloat; 241 case 3: fputs("(long)", out_); return kDouble; 242 // Narrowing-widening. 243 case 4: fputs("(long)(byte)(long)", out_); return kLong; 244 case 5: fputs("(long)(short)(long)", out_); return kLong; 245 case 6: fputs("(long)(int)(long)", out_); return kLong; 246 } 247 } else if (tp == kFloat) { 248 switch (random1(4)) { 249 case 1: fputs("(float)", out_); return kInt; 250 case 2: fputs("(float)", out_); return kLong; 251 case 3: fputs("(float)", out_); return kDouble; 252 // Narrowing-widening. 253 case 4: fputs("(float)(int)(float)", out_); return kFloat; 254 } 255 } else if (tp == kDouble) { 256 switch (random1(5)) { 257 case 1: fputs("(double)", out_); return kInt; 258 case 2: fputs("(double)", out_); return kLong; 259 case 3: fputs("(double)", out_); return kFloat; 260 // Narrowing-widening. 261 case 4: fputs("(double)(int)(double)", out_); return kDouble; 262 case 5: fputs("(double)(float)(double)", out_); return kDouble; 263 } 264 } 265 return tp; // nothing suitable, just keep type 266 } 267 268 // Emit a type conversion (out type given, new suitable in type picked). 269 void emitTypeConversion(Type tp) { 270 if (tp == kBoolean) { 271 Type tp = randomType(); 272 emitExpression(tp); 273 fputc(' ', out_); 274 emitRelationalOp(tp); 275 fputc(' ', out_); 276 emitExpression(tp); 277 } else { 278 tp = emitTypeConversionOp(tp); 279 fputc(' ', out_); 280 emitExpression(tp); 281 } 282 } 283 284 // Emit an unary intrinsic (out type given, new suitable in type picked). 285 Type emitIntrinsic1(Type tp) { 286 if (tp == kBoolean) { 287 switch (random1(6)) { 288 case 1: fputs("Float.isNaN", out_); return kFloat; 289 case 2: fputs("Float.isFinite", out_); return kFloat; 290 case 3: fputs("Float.isInfinite", out_); return kFloat; 291 case 4: fputs("Double.isNaN", out_); return kDouble; 292 case 5: fputs("Double.isFinite", out_); return kDouble; 293 case 6: fputs("Double.isInfinite", out_); return kDouble; 294 } 295 } else if (isInteger(tp)) { 296 const char* prefix = tp == kLong ? "Long" : "Integer"; 297 switch (random1(13)) { 298 case 1: fprintf(out_, "%s.highestOneBit", prefix); break; 299 case 2: fprintf(out_, "%s.lowestOneBit", prefix); break; 300 case 3: fprintf(out_, "%s.numberOfLeadingZeros", prefix); break; 301 case 4: fprintf(out_, "%s.numberOfTrailingZeros", prefix); break; 302 case 5: fprintf(out_, "%s.bitCount", prefix); break; 303 case 6: fprintf(out_, "%s.signum", prefix); break; 304 case 7: fprintf(out_, "%s.reverse", prefix); break; 305 case 8: fprintf(out_, "%s.reverseBytes", prefix); break; 306 case 9: fputs("Math.incrementExact", out_); break; 307 case 10: fputs("Math.decrementExact", out_); break; 308 case 11: fputs("Math.negateExact", out_); break; 309 case 12: fputs("Math.abs", out_); break; 310 case 13: fputs("Math.round", out_); 311 return tp == kLong ? kDouble : kFloat; 312 } 313 } else { // isFP(tp) 314 switch (random1(6)) { 315 case 1: fputs("Math.abs", out_); break; 316 case 2: fputs("Math.ulp", out_); break; 317 case 3: fputs("Math.signum", out_); break; 318 case 4: fputs("Math.nextUp", out_); break; 319 case 5: fputs("Math.nextDown", out_); break; 320 case 6: if (tp == kDouble) { 321 fputs("Double.longBitsToDouble", out_); 322 return kLong; 323 } else { 324 fputs("Float.intBitsToFloat", out_); 325 return kInt; 326 } 327 } 328 } 329 return tp; // same type in-out 330 } 331 332 // Emit a binary intrinsic (out type given, new suitable in type picked). 333 Type emitIntrinsic2(Type tp) { 334 if (tp == kBoolean) { 335 switch (random1(3)) { 336 case 1: fputs("Boolean.logicalAnd", out_); break; 337 case 2: fputs("Boolean.logicalOr", out_); break; 338 case 3: fputs("Boolean.logicalXor", out_); break; 339 } 340 } else if (isInteger(tp)) { 341 const char* prefix = tp == kLong ? "Long" : "Integer"; 342 switch (random1(11)) { 343 case 1: fprintf(out_, "%s.compare", prefix); break; 344 case 2: fprintf(out_, "%s.sum", prefix); break; 345 case 3: fprintf(out_, "%s.min", prefix); break; 346 case 4: fprintf(out_, "%s.max", prefix); break; 347 case 5: fputs("Math.min", out_); break; 348 case 6: fputs("Math.max", out_); break; 349 case 7: fputs("Math.floorDiv", out_); break; 350 case 8: fputs("Math.floorMod", out_); break; 351 case 9: fputs("Math.addExact", out_); break; 352 case 10: fputs("Math.subtractExact", out_); break; 353 case 11: fputs("Math.multiplyExact", out_); break; 354 } 355 } else { // isFP(tp) 356 const char* prefix = tp == kDouble ? "Double" : "Float"; 357 switch (random1(5)) { 358 case 1: fprintf(out_, "%s.sum", prefix); break; 359 case 2: fprintf(out_, "%s.min", prefix); break; 360 case 3: fprintf(out_, "%s.max", prefix); break; 361 case 4: fputs("Math.min", out_); break; 362 case 5: fputs("Math.max", out_); break; 363 } 364 } 365 return tp; // same type in-out 366 } 367 368 // Emit an intrinsic (out type given, new suitable in type picked). 369 void emitIntrinsic(Type tp) { 370 if (random1(2) == 1) { 371 tp = emitIntrinsic1(tp); 372 fputc('(', out_); 373 emitExpression(tp); 374 fputc(')', out_); 375 } else { 376 tp = emitIntrinsic2(tp); 377 fputc('(', out_); 378 emitExpression(tp); 379 fputs(", ", out_); 380 emitExpression(tp); 381 fputc(')', out_); 382 } 383 } 384 385 // Emit a method call (out type given). 386 void emitMethodCall(Type tp) { 387 if (tp != kBoolean && !in_inner_) { 388 // Accept all numerical types (implicit conversion) and when not 389 // declaring inner classes (to avoid infinite recursion). 390 switch (random1(8)) { 391 case 1: fputs("mA.a()", out_); break; 392 case 2: fputs("mB.a()", out_); break; 393 case 3: fputs("mB.x()", out_); break; 394 case 4: fputs("mBX.x()", out_); break; 395 case 5: fputs("mC.s()", out_); break; 396 case 6: fputs("mC.c()", out_); break; 397 case 7: fputs("mC.x()", out_); break; 398 case 8: fputs("mCX.x()", out_); break; 399 } 400 } else { 401 // Fall back to intrinsic. 402 emitIntrinsic(tp); 403 } 404 } 405 406 // Emit unboxing boxed object. 407 void emitUnbox(Type tp) { 408 fputc('(', out_); 409 emitType(tp); 410 fputs(") new ", out_); 411 emitTypeClass(tp); 412 fputc('(', out_); 413 emitExpression(tp); 414 fputc(')', out_); 415 } 416 417 // Emit miscellaneous constructs. 418 void emitMisc(Type tp) { 419 if (tp == kBoolean) { 420 fprintf(out_, "this instanceof %s", in_inner_ ? "X" : "Test"); 421 } else if (isInteger(tp)) { 422 const char* prefix = tp == kLong ? "Long" : "Integer"; 423 switch (random1(2)) { 424 case 1: fprintf(out_, "%s.MIN_VALUE", prefix); break; 425 case 2: fprintf(out_, "%s.MAX_VALUE", prefix); break; 426 } 427 } else { // isFP(tp) 428 const char* prefix = tp == kDouble ? "Double" : "Float"; 429 switch (random1(6)) { 430 case 1: fprintf(out_, "%s.MIN_NORMAL", prefix); break; 431 case 2: fprintf(out_, "%s.MIN_VALUE", prefix); break; 432 case 3: fprintf(out_, "%s.MAX_VALUE", prefix); break; 433 case 4: fprintf(out_, "%s.POSITIVE_INFINITY", prefix); break; 434 case 5: fprintf(out_, "%s.NEGATIVE_INFINITY", prefix); break; 435 case 6: fprintf(out_, "%s.NaN", prefix); break; 436 } 437 } 438 } 439 440 // Adjust local of given type and return adjusted value. 441 uint32_t adjustLocal(Type tp, int32_t a) { 442 switch (tp) { 443 case kBoolean: boolean_local_ += a; return boolean_local_; 444 case kInt: int_local_ += a; return int_local_; 445 case kLong: long_local_ += a; return long_local_; 446 case kFloat: float_local_ += a; return float_local_; 447 default: double_local_ += a; return double_local_; 448 } 449 } 450 451 // Emit an expression that is a strict upper bound for an array index. 452 void emitUpperBound() { 453 if (random1(8) == 1) { 454 fputs("mArray.length", out_); 455 } else if (random1(8) == 1) { 456 fprintf(out_, "%u", random1(array_size_)); // random in range 457 } else { 458 fprintf(out_, "%u", array_size_); 459 } 460 } 461 462 // Emit an array index, usually within proper range. 463 void emitArrayIndex() { 464 if (loop_nest_ > 0 && random1(2) == 1) { 465 fprintf(out_, "i%u", random0(loop_nest_)); 466 } else if (random1(8) == 1) { 467 fputs("mArray.length - 1", out_); 468 } else { 469 fprintf(out_, "%u", random0(array_size_)); // random in range 470 } 471 // Introduce potential off by one errors with low probability. 472 if (random1(100) == 1) { 473 if (random1(2) == 1) { 474 fputs(" - 1", out_); 475 } else { 476 fputs(" + 1", out_); 477 } 478 } 479 } 480 481 // Emit a literal. 482 void emitLiteral(Type tp) { 483 switch (tp) { 484 case kBoolean: fputs(random1(2) == 1 ? "true" : "false", out_); break; 485 case kInt: fprintf(out_, "%d", random()); break; 486 case kLong: fprintf(out_, "%dL", random()); break; 487 case kFloat: fprintf(out_, "%d.0f", random()); break; 488 case kDouble: fprintf(out_, "%d.0", random()); break; 489 } 490 } 491 492 // Emit array variable, if available. 493 bool emitArrayVariable(Type tp) { 494 if (tp == array_type_) { 495 fputs("mArray", out_); 496 for (uint32_t i = 0; i < array_dim_; i++) { 497 fputc('[', out_); 498 emitArrayIndex(); 499 fputc(']', out_); 500 } 501 return true; 502 } 503 return false; 504 } 505 506 // Emit a local variable, if available. 507 bool emitLocalVariable(Type tp) { 508 uint32_t locals = adjustLocal(tp, 0); 509 if (locals > 0) { 510 uint32_t local = random0(locals); 511 switch (tp) { 512 case kBoolean: fprintf(out_, "lZ%u", local); break; 513 case kInt: fprintf(out_, "lI%u", local); break; 514 case kLong: fprintf(out_, "lJ%u", local); break; 515 case kFloat: fprintf(out_, "lF%u", local); break; 516 case kDouble: fprintf(out_, "lD%u", local); break; 517 } 518 return true; 519 } 520 return false; 521 } 522 523 // Emit a field variable. 524 void emitFieldVariable(Type tp) { 525 switch (tp) { 526 case kBoolean:fputs("mZ", out_); break; 527 case kInt: fputs("mI", out_); break; 528 case kLong: fputs("mJ", out_); break; 529 case kFloat: fputs("mF", out_); break; 530 case kDouble: fputs("mD", out_); break; 531 } 532 } 533 534 // Emit a variable. 535 void emitVariable(Type tp) { 536 switch (random1(4)) { 537 case 1: 538 if (emitArrayVariable(tp)) 539 return; 540 // FALL-THROUGH 541 case 2: 542 if (emitLocalVariable(tp)) 543 return; 544 // FALL-THROUGH 545 default: 546 emitFieldVariable(tp); 547 break; 548 } 549 } 550 551 // Emit an expression. 552 void emitExpression(Type tp) { 553 // Continuing expression becomes less likely as the depth grows. 554 if (random1(expr_depth_ + 1) > fuzz_expr_depth_) { 555 if (random1(2) == 1) { 556 emitLiteral(tp); 557 } else { 558 emitVariable(tp); 559 } 560 return; 561 } 562 563 expr_depth_++; 564 565 fputc('(', out_); 566 switch (random1(12)) { // favor binary operations 567 case 1: 568 // Unary operator: ~ x 569 emitUnaryOp(tp); 570 fputc(' ', out_); 571 emitExpression(tp); 572 break; 573 case 2: 574 // Pre-increment: ++x 575 emitIncDecOp(tp); 576 emitVariable(tp); 577 break; 578 case 3: 579 // Post-increment: x++ 580 emitVariable(tp); 581 emitIncDecOp(tp); 582 break; 583 case 4: 584 // Ternary operator: b ? x : y 585 emitExpression(kBoolean); 586 fputs(" ? ", out_); 587 emitExpression(tp); 588 fputs(" : ", out_); 589 emitExpression(tp); 590 break; 591 case 5: 592 // Type conversion: (float) x 593 emitTypeConversion(tp); 594 break; 595 case 6: 596 // Intrinsic: foo(x) 597 emitIntrinsic(tp); 598 break; 599 case 7: 600 // Method call: mA.a() 601 emitMethodCall(tp); 602 break; 603 case 8: 604 // Emit unboxing boxed value: (int) Integer(x) 605 emitUnbox(tp); 606 break; 607 case 9: 608 // Miscellaneous constructs: a.length 609 emitMisc(tp); 610 break; 611 default: 612 // Binary operator: x + y 613 emitExpression(tp); 614 fputc(' ', out_); 615 emitBinaryOp(tp); 616 fputc(' ', out_); 617 emitExpression(tp); 618 break; 619 } 620 fputc(')', out_); 621 622 --expr_depth_; 623 } 624 625 // 626 // Statements. 627 // 628 629 // Emit current indentation. 630 void emitIndentation() const { 631 for (uint32_t i = 0; i < indentation_; i++) { 632 fputc(' ', out_); 633 } 634 } 635 636 // Emit a return statement. 637 bool emitReturn(bool mustEmit) { 638 // Only emit when we must, or with low probability inside ifs/loops, 639 // but outside do-while to avoid confusing the may follow status. 640 if (mustEmit || ((if_nest_ + loop_nest_) > 0 && do_nest_ == 0 && random1(10) == 1)) { 641 fputs("return ", out_); 642 emitExpression(return_type_); 643 fputs(";\n", out_); 644 return false; 645 } 646 // Fall back to assignment. 647 return emitAssignment(); 648 } 649 650 // Emit a continue statement. 651 bool emitContinue() { 652 // Only emit with low probability inside loops. 653 if (loop_nest_ > 0 && random1(10) == 1) { 654 fputs("continue;\n", out_); 655 return false; 656 } 657 // Fall back to assignment. 658 return emitAssignment(); 659 } 660 661 // Emit a break statement. 662 bool emitBreak() { 663 // Only emit with low probability inside loops, but outside switches 664 // to avoid confusing the may follow status. 665 if (loop_nest_ > 0 && switch_nest_ == 0 && random1(10) == 1) { 666 fputs("break;\n", out_); 667 return false; 668 } 669 // Fall back to assignment. 670 return emitAssignment(); 671 } 672 673 // Emit a new scope with a local variable declaration statement. 674 bool emitScope() { 675 Type tp = randomType(); 676 fputs("{\n", out_); 677 indentation_ += 2; 678 emitIndentation(); 679 emitType(tp); 680 switch (tp) { 681 case kBoolean: fprintf(out_, " lZ%u = ", boolean_local_); break; 682 case kInt: fprintf(out_, " lI%u = ", int_local_); break; 683 case kLong: fprintf(out_, " lJ%u = ", long_local_); break; 684 case kFloat: fprintf(out_, " lF%u = ", float_local_); break; 685 case kDouble: fprintf(out_, " lD%u = ", double_local_); break; 686 } 687 emitExpression(tp); 688 fputs(";\n", out_); 689 690 adjustLocal(tp, 1); // local now visible 691 692 bool mayFollow = emitStatementList(); 693 694 adjustLocal(tp, -1); // local no longer visible 695 696 indentation_ -= 2; 697 emitIndentation(); 698 fputs("}\n", out_); 699 return mayFollow; 700 } 701 702 // Emit one dimension of an array initializer, where parameter dim >= 1 703 // denotes the number of remaining dimensions that should be emitted. 704 void emitArrayInitDim(int dim) { 705 if (dim == 1) { 706 // Last dimension: set of values. 707 fputs("{ ", out_); 708 for (uint32_t i = 0; i < array_size_; i++) { 709 emitExpression(array_type_); 710 fputs(", ", out_); 711 } 712 fputs("}", out_); 713 714 } else { 715 // Outer dimensions: set of sets. 716 fputs("{\n", out_); 717 indentation_ += 2; 718 emitIndentation(); 719 720 for (uint32_t i = 0; i < array_size_; i++) { 721 emitArrayInitDim(dim - 1); 722 if (i != array_size_ - 1) { 723 fputs(",\n", out_); 724 emitIndentation(); 725 } 726 } 727 728 fputs(",\n", out_); 729 indentation_ -= 2; 730 emitIndentation(); 731 fputs("}", out_); 732 } 733 } 734 735 // Emit an array initializer of the following form. 736 // { 737 // type[]..[] tmp = { .. }; 738 // mArray = tmp; 739 // } 740 bool emitArrayInit() { 741 // Avoid elaborate array initializers. 742 uint64_t p = pow(array_size_, array_dim_); 743 if (p > 20) { 744 return emitAssignment(); // fall back 745 } 746 747 fputs("{\n", out_); 748 749 indentation_ += 2; 750 emitIndentation(); 751 emitType(array_type_); 752 for (uint32_t i = 0; i < array_dim_; i++) { 753 fputs("[]", out_); 754 } 755 fputs(" tmp = ", out_); 756 emitArrayInitDim(array_dim_); 757 fputs(";\n", out_); 758 759 emitIndentation(); 760 fputs("mArray = tmp;\n", out_); 761 762 indentation_ -= 2; 763 emitIndentation(); 764 fputs("}\n", out_); 765 return true; 766 } 767 768 // Emit a for loop. 769 bool emitForLoop() { 770 // Continuing loop nest becomes less likely as the depth grows. 771 if (random1(loop_nest_ + 1) > fuzz_loop_nest_) { 772 return emitAssignment(); // fall back 773 } 774 775 bool goesUp = random1(2) == 1; 776 fprintf(out_, "for (int i%u = ", loop_nest_); 777 if (goesUp) { 778 fprintf(out_, "0; i%u < ", loop_nest_); 779 emitUpperBound(); 780 fprintf(out_, "; i%u++) {\n", loop_nest_); 781 } else { 782 emitUpperBound(); 783 fprintf(out_, " - 1; i%d >= 0", loop_nest_); 784 fprintf(out_, "; i%d--) {\n", loop_nest_); 785 } 786 787 ++loop_nest_; // now in loop 788 789 indentation_ += 2; 790 emitStatementList(); 791 792 --loop_nest_; // no longer in loop 793 794 indentation_ -= 2; 795 emitIndentation(); 796 fprintf(out_, "}\n"); 797 return true; // loop-body does not block flow 798 } 799 800 // Emit while or do-while loop. 801 bool emitDoLoop() { 802 // Continuing loop nest becomes less likely as the depth grows. 803 if (random1(loop_nest_ + 1) > fuzz_loop_nest_) { 804 return emitAssignment(); // fall back 805 } 806 807 // TODO: remove this 808 // The jack bug b/28862040 prevents generating while/do-while loops because otherwise 809 // we get dozens of reports on the same issue per nightly/ run. 810 if (true) { 811 return emitAssignment(); 812 } 813 814 bool isWhile = random1(2) == 1; 815 fputs("{\n", out_); 816 indentation_ += 2; 817 emitIndentation(); 818 fprintf(out_, "int i%u = %d;", loop_nest_, isWhile ? -1 : 0); 819 emitIndentation(); 820 if (isWhile) { 821 fprintf(out_, "while (++i%u < ", loop_nest_); 822 emitUpperBound(); 823 fputs(") {\n", out_); 824 } else { 825 fputs("do {\n", out_); 826 do_nest_++; 827 } 828 829 ++loop_nest_; // now in loop 830 831 indentation_ += 2; 832 emitStatementList(); 833 834 --loop_nest_; // no longer in loop 835 836 indentation_ -= 2; 837 emitIndentation(); 838 if (isWhile) { 839 fputs("}\n", out_); 840 } else { 841 fprintf(out_, "} while (++i%u < ", loop_nest_); 842 emitUpperBound(); 843 fputs(");\n", out_); 844 --do_nest_; 845 } 846 indentation_ -= 2; 847 emitIndentation(); 848 fputs("}\n", out_); 849 return true; // loop-body does not block flow 850 } 851 852 // Emit an if statement. 853 bool emitIfStmt() { 854 // Continuing if nest becomes less likely as the depth grows. 855 if (random1(if_nest_ + 1) > fuzz_if_nest_) { 856 return emitAssignment(); // fall back 857 } 858 859 fputs("if (", out_); 860 emitExpression(kBoolean); 861 fputs(") {\n", out_); 862 863 ++if_nest_; // now in if 864 865 indentation_ += 2; 866 bool mayFollowTrue = emitStatementList(); 867 indentation_ -= 2; 868 emitIndentation(); 869 fprintf(out_, "} else {\n"); 870 indentation_ += 2; 871 bool mayFollowFalse = emitStatementList(); 872 873 --if_nest_; // no longer in if 874 875 indentation_ -= 2; 876 emitIndentation(); 877 fprintf(out_, "}\n"); 878 return mayFollowTrue || mayFollowFalse; 879 } 880 881 // Emit a switch statement. 882 bool emitSwitch() { 883 // Continuing if nest becomes less likely as the depth grows. 884 if (random1(if_nest_ + 1) > fuzz_if_nest_) { 885 return emitAssignment(); // fall back 886 } 887 888 bool mayFollow = false; 889 fputs("switch (", out_); 890 emitArrayIndex(); // restrict its range 891 fputs(") {\n", out_); 892 893 ++if_nest_; 894 ++switch_nest_; // now in switch 895 896 indentation_ += 2; 897 for (uint32_t i = 0; i < 2; i++) { 898 emitIndentation(); 899 if (i == 0) { 900 fprintf(out_, "case %u: {\n", random0(array_size_)); 901 } else { 902 fprintf(out_, "default: {\n"); 903 } 904 indentation_ += 2; 905 if (emitStatementList()) { 906 // Must end with break. 907 emitIndentation(); 908 fputs("break;\n", out_); 909 mayFollow = true; 910 } 911 indentation_ -= 2; 912 emitIndentation(); 913 fputs("}\n", out_); 914 } 915 916 --if_nest_; 917 --switch_nest_; // no longer in switch 918 919 indentation_ -= 2; 920 emitIndentation(); 921 fprintf(out_, "}\n"); 922 return mayFollow; 923 } 924 925 // Emit an assignment statement. 926 bool emitAssignment() { 927 Type tp = randomType(); 928 emitVariable(tp); 929 fputc(' ', out_); 930 emitAssignmentOp(tp); 931 fputc(' ', out_); 932 emitExpression(tp); 933 fputs(";\n", out_); 934 return true; 935 } 936 937 // Emit a single statement. Returns true if statements may follow. 938 bool emitStatement() { 939 switch (random1(16)) { // favor assignments 940 case 1: return emitReturn(false); break; 941 case 2: return emitContinue(); break; 942 case 3: return emitBreak(); break; 943 case 4: return emitScope(); break; 944 case 5: return emitArrayInit(); break; 945 case 6: return emitForLoop(); break; 946 case 7: return emitDoLoop(); break; 947 case 8: return emitIfStmt(); break; 948 case 9: return emitSwitch(); break; 949 default: return emitAssignment(); break; 950 } 951 } 952 953 // Emit a statement list. Returns true if statements may follow. 954 bool emitStatementList() { 955 while (stmt_length_ < 1000) { // avoid run-away 956 stmt_length_++; 957 emitIndentation(); 958 if (!emitStatement()) { 959 return false; // rest would be dead code 960 } 961 // Continuing this list becomes less likely as the total statement list grows. 962 if (random1(stmt_length_) > fuzz_stmt_length_) { 963 break; 964 } 965 } 966 return true; 967 } 968 969 // Emit interface and class declarations. 970 void emitClassDecls() { 971 in_inner_ = true; 972 fputs(" private interface X {\n", out_); 973 fputs(" int x();\n", out_); 974 fputs(" }\n\n", out_); 975 fputs(" private class A {\n", out_); 976 fputs(" public int a() {\n", out_); 977 fputs(" return ", out_); 978 emitExpression(kInt); 979 fputs(";\n }\n", out_); 980 fputs(" }\n\n", out_); 981 fputs(" private class B extends A implements X {\n", out_); 982 fputs(" public int a() {\n", out_); 983 fputs(" return super.a() + ", out_); 984 emitExpression(kInt); 985 fputs(";\n }\n", out_); 986 fputs(" public int x() {\n", out_); 987 fputs(" return ", out_); 988 emitExpression(kInt); 989 fputs(";\n }\n", out_); 990 fputs(" }\n\n", out_); 991 fputs(" private static class C implements X {\n", out_); 992 fputs(" public static int s() {\n", out_); 993 fputs(" return ", out_); 994 emitLiteral(kInt); 995 fputs(";\n }\n", out_); 996 fputs(" public int c() {\n", out_); 997 fputs(" return ", out_); 998 emitLiteral(kInt); 999 fputs(";\n }\n", out_); 1000 fputs(" public int x() {\n", out_); 1001 fputs(" return ", out_); 1002 emitLiteral(kInt); 1003 fputs(";\n }\n", out_); 1004 fputs(" }\n\n", out_); 1005 in_inner_ = false; 1006 } 1007 1008 // Emit field declarations. 1009 void emitFieldDecls() { 1010 fputs(" private A mA = new B();\n", out_); 1011 fputs(" private B mB = new B();\n", out_); 1012 fputs(" private X mBX = new B();\n", out_); 1013 fputs(" private C mC = new C();\n", out_); 1014 fputs(" private X mCX = new C();\n\n", out_); 1015 fputs(" private boolean mZ = false;\n", out_); 1016 fputs(" private int mI = 0;\n", out_); 1017 fputs(" private long mJ = 0;\n", out_); 1018 fputs(" private float mF = 0;\n", out_); 1019 fputs(" private double mD = 0;\n\n", out_); 1020 } 1021 1022 // Emit array declaration. 1023 void emitArrayDecl() { 1024 fputs(" private ", out_); 1025 emitType(array_type_); 1026 for (uint32_t i = 0; i < array_dim_; i++) { 1027 fputs("[]", out_); 1028 } 1029 fputs(" mArray = new ", out_); 1030 emitType(array_type_); 1031 for (uint32_t i = 0; i < array_dim_; i++) { 1032 fprintf(out_, "[%d]", array_size_); 1033 } 1034 fputs(";\n\n", out_); 1035 } 1036 1037 // Emit test constructor. 1038 void emitTestConstructor() { 1039 fputs(" private Test() {\n", out_); 1040 indentation_ += 2; 1041 emitIndentation(); 1042 emitType(array_type_); 1043 fputs(" a = ", out_); 1044 emitLiteral(array_type_); 1045 fputs(";\n", out_); 1046 for (uint32_t i = 0; i < array_dim_; i++) { 1047 emitIndentation(); 1048 fprintf(out_, "for (int i%u = 0; i%u < %u; i%u++) {\n", i, i, array_size_, i); 1049 indentation_ += 2; 1050 } 1051 emitIndentation(); 1052 fputs("mArray", out_); 1053 for (uint32_t i = 0; i < array_dim_; i++) { 1054 fprintf(out_, "[i%u]", i); 1055 } 1056 fputs(" = a;\n", out_); 1057 emitIndentation(); 1058 if (array_type_ == kBoolean) { 1059 fputs("a = !a;\n", out_); 1060 } else { 1061 fputs("a++;\n", out_); 1062 } 1063 for (uint32_t i = 0; i < array_dim_; i++) { 1064 indentation_ -= 2; 1065 emitIndentation(); 1066 fputs("}\n", out_); 1067 } 1068 indentation_ -= 2; 1069 fputs(" }\n\n", out_); 1070 } 1071 1072 // Emit test method. 1073 void emitTestMethod() { 1074 fputs(" private ", out_); 1075 emitType(return_type_); 1076 fputs(" testMethod() {\n", out_); 1077 indentation_ += 2; 1078 if (emitStatementList()) { 1079 // Must end with return. 1080 emitIndentation(); 1081 emitReturn(true); 1082 } 1083 indentation_ -= 2; 1084 fputs(" }\n\n", out_); 1085 } 1086 1087 // Emit main method driver. 1088 void emitMainMethod() { 1089 fputs(" public static void main(String[] args) {\n", out_); 1090 indentation_ += 2; 1091 fputs(" Test t = new Test();\n ", out_); 1092 emitType(return_type_); 1093 fputs(" r = ", out_); 1094 emitLiteral(return_type_); 1095 fputs(";\n", out_); 1096 fputs(" try {\n", out_); 1097 fputs(" r = t.testMethod();\n", out_); 1098 fputs(" } catch (Exception e) {\n", out_); 1099 fputs(" // Arithmetic, null pointer, index out of bounds, etc.\n", out_); 1100 fputs(" System.out.println(\"An exception was caught.\");\n", out_); 1101 fputs(" }\n", out_); 1102 fputs(" System.out.println(\"r = \" + r);\n", out_); 1103 fputs(" System.out.println(\"mZ = \" + t.mZ);\n", out_); 1104 fputs(" System.out.println(\"mI = \" + t.mI);\n", out_); 1105 fputs(" System.out.println(\"mJ = \" + t.mJ);\n", out_); 1106 fputs(" System.out.println(\"mF = \" + t.mF);\n", out_); 1107 fputs(" System.out.println(\"mD = \" + t.mD);\n", out_); 1108 fputs(" System.out.println(\"mArray = \" + ", out_); 1109 if (array_dim_ == 1) { 1110 fputs("Arrays.toString(t.mArray)", out_); 1111 } else { 1112 fputs("Arrays.deepToString(t.mArray)", out_); 1113 } 1114 fputs(");\n", out_); 1115 indentation_ -= 2; 1116 fputs(" }\n", out_); 1117 } 1118 1119 // Emit program header. Emit command line options in the comments. 1120 void emitHeader() { 1121 fputs("\n/**\n * AOSP JFuzz Tester.\n", out_); 1122 fputs(" * Automatically generated program.\n", out_); 1123 fprintf(out_, 1124 " * jfuzz -s %u -d %u -l %u -i %u -n %u (version %s)\n */\n\n", 1125 fuzz_seed_, 1126 fuzz_expr_depth_, 1127 fuzz_stmt_length_, 1128 fuzz_if_nest_, 1129 fuzz_loop_nest_, 1130 VERSION); 1131 fputs("import java.util.Arrays;\n\n", out_); 1132 } 1133 1134 // Emit single test class with main driver. 1135 void emitTestClassWithMain() { 1136 fputs("public class Test {\n\n", out_); 1137 indentation_ += 2; 1138 emitClassDecls(); 1139 emitFieldDecls(); 1140 emitArrayDecl(); 1141 emitTestConstructor(); 1142 emitTestMethod(); 1143 emitMainMethod(); 1144 indentation_ -= 2; 1145 fputs("}\n\n", out_); 1146 } 1147 1148 // 1149 // Random integers. 1150 // 1151 1152 // Return random integer. 1153 int32_t random() { 1154 return fuzz_random_engine_(); 1155 } 1156 1157 // Return random integer in range [0,max). 1158 uint32_t random0(uint32_t max) { 1159 std::uniform_int_distribution<uint32_t> gen(0, max - 1); 1160 return gen(fuzz_random_engine_); 1161 } 1162 1163 // Return random integer in range [1,max]. 1164 uint32_t random1(uint32_t max) { 1165 std::uniform_int_distribution<uint32_t> gen(1, max); 1166 return gen(fuzz_random_engine_); 1167 } 1168 1169 // Fuzzing parameters. 1170 FILE* out_; 1171 std::mt19937 fuzz_random_engine_; 1172 const uint32_t fuzz_seed_; 1173 const uint32_t fuzz_expr_depth_; 1174 const uint32_t fuzz_stmt_length_; 1175 const uint32_t fuzz_if_nest_; 1176 const uint32_t fuzz_loop_nest_; 1177 1178 // Return and array setup. 1179 const Type return_type_; 1180 const Type array_type_; 1181 const uint32_t array_dim_; 1182 const uint32_t array_size_; 1183 1184 // Current context. 1185 uint32_t indentation_; 1186 uint32_t expr_depth_; 1187 uint32_t stmt_length_; 1188 uint32_t if_nest_; 1189 uint32_t loop_nest_; 1190 uint32_t switch_nest_; 1191 uint32_t do_nest_; 1192 uint32_t boolean_local_; 1193 uint32_t int_local_; 1194 uint32_t long_local_; 1195 uint32_t float_local_; 1196 uint32_t double_local_; 1197 bool in_inner_; 1198 }; 1199 1200 } // anonymous namespace 1201 1202 int32_t main(int32_t argc, char** argv) { 1203 // Time-based seed. 1204 struct timeval tp; 1205 gettimeofday(&tp, NULL); 1206 1207 // Defaults. 1208 uint32_t seed = (tp.tv_sec * 1000000 + tp.tv_usec); 1209 uint32_t expr_depth = 1; 1210 uint32_t stmt_length = 8; 1211 uint32_t if_nest = 2; 1212 uint32_t loop_nest = 3; 1213 1214 // Parse options. 1215 while (1) { 1216 int32_t option = getopt(argc, argv, "s:d:l:i:n:vh"); 1217 if (option < 0) { 1218 break; // done 1219 } 1220 switch (option) { 1221 case 's': 1222 seed = strtoul(optarg, nullptr, 0); // deterministic seed 1223 break; 1224 case 'd': 1225 expr_depth = strtoul(optarg, nullptr, 0); 1226 break; 1227 case 'l': 1228 stmt_length = strtoul(optarg, nullptr, 0); 1229 break; 1230 case 'i': 1231 if_nest = strtoul(optarg, nullptr, 0); 1232 break; 1233 case 'n': 1234 loop_nest = strtoul(optarg, nullptr, 0); 1235 break; 1236 case 'v': 1237 fprintf(stderr, "jfuzz version %s\n", VERSION); 1238 return 0; 1239 case 'h': 1240 default: 1241 fprintf(stderr, 1242 "usage: %s [-s seed] " 1243 "[-d expr-depth] [-l stmt-length] " 1244 "[-i if-nest] [-n loop-nest] [-v] [-h]\n", 1245 argv[0]); 1246 return 1; 1247 } 1248 } 1249 1250 // Seed global random generator. 1251 srand(seed); 1252 1253 // Generate fuzzed program. 1254 JFuzz fuzz(stdout, seed, expr_depth, stmt_length, if_nest, loop_nest); 1255 fuzz.emitProgram(); 1256 return 0; 1257 } 1258