Skip to content

Commit 52fe951

Browse files
author
bors-servo
authored
Auto merge of #1080 - fitzgen:creduce-in-driver-py, r=pepyakin
Automatically run `creduce` in `csmith-fuzzing/driver.py` Reduced test cases FTW \o/ r? @emilio or @pepyakin Also, this prints out everything needed to file a bug report; just copy paste! For example, this is what it looks like when I ran it most recently: <details><pre><code> $ ./driver.py Fuzzing `bindgen` with C-Smith... Iteration: 0 Error: ['./predicate.py', '--bindgen-args', '--with-derive-partialeq --with-derive-eq --with-derive-partialord --with-derive-ord --with-derive-hash --with-derive-default -- -I/home/fitzgen/rust-bindgen/csmith-fuzzing', '/tmp/input-uij7lxep.h'] exited with code 1 +Running: ['cargo', 'run', '--manifest-path', '/home/fitzgen/rust-bindgen/Cargo.toml', '--', '/tmp/input-uij7lxep.h', '-o', '/tmp/bindings-vyl0qlte.rs', '--with-derive-partialeq', '--with-derive-eq', '--with-derive-partialord', '--with-derive-ord', '--with-derive-hash', '--with-derive-default', '--', '-I/home/fitzgen/rust-bindgen/csmith-fuzzing'] +Running: ['rustc', '--crate-type', 'lib', '--test', '-o', '/tmp/layout-tests-41kuqr8x', '/tmp/bindings-vyl0qlte.rs'] +Error: running `rustc` on the emitted bindings failed ++error[E0600]: cannot apply unary operator `-` to type `u32` ++ --> /tmp/bindings-vyl0qlte.rs:27:333 ++ | ++27 | } pub const g_79 : :: std :: os :: raw :: c_ushort = 1 ; pub const g_83 : :: std :: os :: raw :: c_schar = -50 ; pub const g_86 : :: std :: os :: raw :: c_int = -417508947 ; pub const g_93 : :: std :: os :: raw :: c_int = -9 ; pub const g_122 : :: std :: os :: raw :: c_short = 1 ; pub const g_124 : :: std :: os :: raw :: c_uint = -5 ; extern "C" { ++ | ^^ ++ ++error: aborting due to previous error ++ -------------------- Failing test case: /tmp/input-uij7lxep.h -------------------- /* * This is a RANDOMLY GENERATED PROGRAM. * * Generator: csmith 2.2.0 * Git version: dcef523 * Options: -o /tmp/input-uij7lxep.h --no-checksum --nomain --max-block-size 1 --max-block-depth 1 * Seed: 1763418240 */ #include "csmith.h" volatile uint64_t csmith_sink_ = 0; static long __undefined; /* --- Struct/Union Declarations --- */ union U1 { const volatile int32_t f0; }; union U2 { volatile int64_t f0; }; /* --- GLOBAL VARIABLES --- */ static uint64_t g_9[10] = {0x8E418A52733582F8LL,7UL,0x8E418A52733582F8LL,0x8E418A52733582F8LL,7UL,0x8E418A52733582F8LL,0x8E418A52733582F8LL,7UL,0x8E418A52733582F8LL,0x8E418A52733582F8LL}; static int32_t g_23 = (-1L); static uint8_t g_26[6] = {1UL,1UL,1UL,1UL,1UL,1UL}; static uint8_t g_28 = 0x94L; static int32_t g_30[2] = {(-1L),(-1L)}; static volatile union U2 g_71 = {-1L};/* VOLATILE GLOBAL g_71 */ static int32_t *g_73 = &g_23; static int32_t **g_72 = &g_73; static const union U1 g_77 = {-9L};/* VOLATILE GLOBAL g_77 */ static uint16_t g_79 = 1UL; static int8_t g_83 = 0xCEL; static int32_t g_86 = 0xE71D51ADL; static int32_t g_93 = (-9L); static int16_t g_122 = 1L; static uint32_t g_124 = 18446744073709551611UL; static uint16_t g_127[7] = {0x42CEL,0x3A86L,0x42CEL,0x42CEL,0x3A86L,0x42CEL,0x42CEL}; static uint32_t g_128 = 1UL; static int8_t g_130 = 0xF4L; static const int32_t *g_135 = &g_23; static const int32_t ** volatile g_134 = &g_135;/* VOLATILE GLOBAL g_134 */ /* --- FORWARD DECLARATIONS --- */ static uint64_t func_1(void); static const int32_t * func_2(uint32_t p_3); static int64_t func_6(uint32_t p_7, int32_t p_8); static int32_t func_11(int64_t p_12); static int32_t func_15(const uint8_t p_16, int32_t p_17, int32_t * p_18, uint32_t p_19); static uint8_t func_20(int32_t * const p_21); static int32_t * const func_33(int64_t p_34, uint8_t p_35); static int32_t * func_43(uint16_t p_44, int32_t p_45, int32_t * p_46, uint32_t p_47, const int64_t p_48); static int8_t func_57(int16_t p_58, uint64_t p_59, int32_t p_60, uint32_t p_61); static const union U1 func_66(int32_t p_67, int32_t p_68, uint32_t p_69, int32_t p_70); /* --- FUNCTIONS --- */ /* ------------------------------------------ */ /* * reads : g_9 g_23 g_26 g_30 g_71 g_72 g_73 g_77 g_83 g_86 g_79 g_122 g_28 g_71.f0 g_127 g_128 g_134 * writes: g_23 g_26 g_30 g_73 g_79 g_83 g_86 g_93 g_122 g_127 g_135 */ static uint64_t func_1(void) { /* block id: 0 */ uint32_t l_10 = 0x58E17C10L; int64_t *l_92 = (void*)0; const int32_t **l_133 = (void*)0; (*g_134) = func_2((safe_sub_func_int64_t_s_s((g_93 = func_6((g_9[8] , l_10), func_11(g_9[6]))), (-1L)))); return l_10; } /* ------------------------------------------ */ /* * reads : g_79 g_73 g_23 g_83 g_30 g_122 g_28 g_71.f0 g_9 g_127 g_128 g_72 * writes: g_79 g_23 g_122 g_127 */ static const int32_t * func_2(uint32_t p_3) { /* block id: 46 */ int64_t l_96[8][8][4] = {{{0x2714D024A44AA9F2LL,0xC90574D26467E2B5LL,3L,0xE8BAC2835E52A12ELL},{1L,(-7L),1L,1L},{1L,1L,(-1L),0x389D4FE02E2238E9LL},{1L,6L,0x389D4FE02E2238E9LL,(-1L)},{(-5L),(-1L),0xBF1637F256DA865BLL,3L},{0xA819422B6A99605DLL,0xBF1637F256DA865BLL,0xBF1637F256DA865BLL,6L},{(-1L),0xA122FC4CEA799ADALL,0x3E7469BA6CE2C691LL,0xB04FC3DD168C87B4LL},{(-1L),(-5L),0xC90574D26467E2B5LL,1L}},{{1L,6L,0L,1L},{(-6L),(-5L),0xAE3508C96F5F53E4LL,0xB04FC3DD168C87B4LL},{1L,0xA122FC4CEA799ADALL,0xE8BAC2835E52A12ELL,6L},{(-10L),0xBF1637F256DA865BLL,0xA819422B6A99605DLL,3L},{1L,(-10L),(-5L),0x2714D024A44AA9F2LL},{0xA819422B6A99605DLL,0xE8BAC2835E52A12ELL,1L,(-7L)},{0xA122FC4CEA799ADALL,0x389D4FE02E2238E9LL,1L,0x389D4FE02E2238E9LL},{0xA75F9311F6BCDC6FLL,0xA819422B6A99605DLL,1L,(-1L)}},{{1L,(-6L),0x2714D024A44AA9F2LL,1L},{1L,0x8765FAFB16363166LL,(-1L),0x9157731B4BD6B462LL},{1L,(-1L),0x2714D024A44AA9F2LL,(-2L)},{1L,0x9157731B4BD6B462LL,1L,(-1L)},{0xA75F9311F6BCDC6FLL,0xB04FC3DD168C87B4LL,1L,0xC90574D26467E2B5LL},{0xA122FC4CEA799ADALL,0x593F29F9B9B769E5LL,1L,(-1L)},{0xA819422B6A99605DLL,1L,(-5L),9L},{1L,0xAE3508C96F5F53E4LL,0xA819422B6A99605DLL,0xA819422B6A99605DLL}},{{(-10L),(-10L),0xE8BAC2835E52A12ELL,0x8765FAFB16363166LL},{1L,(-2L),0xAE3508C96F5F53E4LL,0xA122FC4CEA799ADALL},{(-6L),(-1L),0L,0xAE3508C96F5F53E4LL},{1L,(-1L),0xC90574D26467E2B5LL,0xA122FC4CEA799ADALL},{(-1L),(-2L),0x3E7469BA6CE2C691LL,0x8765FAFB16363166LL},{(-1L),(-10L),0xBF1637F256DA865BLL,0xA819422B6A99605DLL},{6L,0xAE3508C96F5F53E4LL,(-10L),9L},{(-1L),1L,(-7L),(-1L)}},{{1L,0x593F29F9B9B769E5LL,(-10L),0xC90574D26467E2B5LL},{0x9157731B4BD6B462LL,0xB04FC3DD168C87B4LL,0x9157731B4BD6B462LL,(-1L)},{1L,0x9157731B4BD6B462LL,3L,(-2L)},{0xC90574D26467E2B5LL,(-1L),0xA122FC4CEA799ADALL,0x9157731B4BD6B462LL},{(-5L),0x8765FAFB16363166LL,0xA122FC4CEA799ADALL,1L},{0xC90574D26467E2B5LL,(-6L),3L,(-1L)},{1L,0xA819422B6A99605DLL,0x9157731B4BD6B462LL,0x389D4FE02E2238E9LL},{0x9157731B4BD6B462LL,0x389D4FE02E2238E9LL,(-10L),(-7L)}},{{1L,0xE8BAC2835E52A12ELL,(-7L),0x2714D024A44AA9F2LL},{(-1L),(-10L),(-10L),3L},{6L,0xBF1637F256DA865BLL,0xBF1637F256DA865BLL,6L},{(-1L),0xA122FC4CEA799ADALL,0x3E7469BA6CE2C691LL,0xB04FC3DD168C87B4LL},{(-1L),(-5L),0xC90574D26467E2B5LL,1L},{1L,6L,0L,1L},{(-6L),(-5L),0xAE3508C96F5F53E4LL,0xB04FC3DD168C87B4LL},{1L,0xA122FC4CEA799ADALL,0xE8BAC2835E52A12ELL,6L}},{{(-10L),0xBF1637F256DA865BLL,0xA819422B6A99605DLL,3L},{1L,(-10L),(-5L),0x2714D024A44AA9F2LL},{0xA819422B6A99605DLL,0xE8BAC2835E52A12ELL,1L,(-7L)},{0xA122FC4CEA799ADALL,0x389D4FE02E2238E9LL,1L,0x389D4FE02E2238E9LL},{0xA75F9311F6BCDC6FLL,0xA819422B6A99605DLL,1L,(-1L)},{9L,(-1L),0xC90574D26467E2B5LL,1L},{1L,0x2BD54EFE8F334EEALL,(-5L),0xA75F9311F6BCDC6FLL},{1L,0x2714D024A44AA9F2LL,0xC90574D26467E2B5LL,3L}},{{9L,0xA75F9311F6BCDC6FLL,1L,0xAE3508C96F5F53E4LL},{0x3E7469BA6CE2C691LL,0x593F29F9B9B769E5LL,0x9157731B4BD6B462LL,(-6L)},{1L,0xBF1637F256DA865BLL,1L,(-10L)},{6L,0x389D4FE02E2238E9LL,(-1L),0x8765FAFB16363166LL},{0x9157731B4BD6B462LL,(-1L),6L,6L},{1L,1L,(-1L),0x2BD54EFE8F334EEALL},{0x389D4FE02E2238E9LL,3L,(-1L),1L},{(-1L),(-10L),1L,(-1L)}}}; uint16_t *l_101 = (void*)0; uint16_t *l_102 = &g_79; int16_t *l_121 = &g_122; uint32_t *l_123[8] = {&g_124,&g_124,&g_124,&g_124,&g_124,&g_124,&g_124,&g_124}; int32_t l_125 = 0xD58AA24FL; uint16_t *l_126 = &g_127[5]; int8_t *l_129[9] = {&g_83,&g_83,&g_83,&g_83,&g_83,&g_83,&g_83,&g_83,&g_83}; int32_t l_131 = (-9L); int32_t l_132[1]; int i, j, k; for (i = 0; i < 1; i++) l_132[i] = 0x27581F2DL; l_132[0] &= (((safe_lshift_func_int8_t_s_s(l_96[0][3][3], 4)) >= (l_131 |= ((((safe_rshift_func_uint8_t_u_u((safe_sub_func_int64_t_s_s(((((*l_102)++) ^ ((safe_unary_minus_func_uint64_t_u((((0xA2D7867E7C57241CLL && (safe_mul_func_int16_t_s_s((((*l_126) = (safe_mul_func_int16_t_s_s(((safe_add_func_int8_t_s_s(p_3, (((l_125 = (~(p_3 , ((((*g_73) &= (!l_96[0][3][3])) == (safe_lshift_func_int8_t_s_u(g_83, ((((((~l_96[0][3][3]) , (((safe_mul_func_int16_t_s_s(((*l_121) &= (l_96[1][4][2] >= (safe_rshift_func_int8_t_s_s(((p_3 > p_3) > p_3), g_30[0])))), 65535UL)) , l_96[0][3][3]) != l_96[0][3][3])) , p_3) || 0L) ^ 0x232EDDAFL) , g_28)))) <= 0x20AB37EAL)))) , l_96[1][1][1]) || p_3))) == 0x7A964C9DL), p_3))) <= 0xC26FL), g_71.f0))) <= 65534UL) == p_3))) , g_71.f0)) & g_30[0]), (-2L))), g_9[8])) > p_3) && g_127[4]) <= g_128))) , (-1L)); return (*g_72); } /* ------------------------------------------ */ /* * reads : g_86 g_72 g_73 * writes: g_23 */ static int64_t func_6(uint32_t p_7, int32_t p_8) { /* block id: 41 */ uint8_t *l_90 = &g_26[3]; int32_t l_91[10] = {0xE2C54351L,0xC5D07927L,0xE2C54351L,(-1L),(-1L),0xE2C54351L,0xC5D07927L,0xE2C54351L,(-1L),(-1L)}; int i; (**g_72) = (safe_unary_minus_func_int64_t_s(((0UL > (safe_div_func_uint64_t_u_u(g_86, 0x5F43E010D33A1293LL))) || (l_91[2] = (l_90 != l_90))))); return l_91[2]; } /* ------------------------------------------ */ /* * reads : g_9 g_23 g_26 g_30 g_71 g_72 g_73 g_77 g_83 g_86 * writes: g_23 g_26 g_30 g_73 g_79 g_83 g_86 */ static int32_t func_11(int64_t p_12) { /* block id: 1 */ int32_t * const l_22 = &g_23; uint8_t * const l_27 = &g_28; for (p_12 = (-6); (p_12 == (-7)); p_12 = safe_sub_func_uint8_t_u_u(p_12, 8)) { /* block id: 4 */ uint8_t *l_25 = &g_26[5]; int32_t *l_29 = &g_30[0]; int32_t *l_85 = &g_86; (*l_85) |= ((*l_22) = func_15(((*l_25) = func_20(l_22)), (l_27 != l_27), l_29, p_12)); } return (*l_22); } /* ------------------------------------------ */ /* * reads : g_26 g_30 g_9 g_23 g_71 g_72 g_73 g_77 g_83 * writes: g_30 g_23 g_73 g_79 g_83 */ static int32_t func_15(const uint8_t p_16, int32_t p_17, int32_t * p_18, uint32_t p_19) { /* block id: 9 */ const uint32_t l_36[2][8] = {{0xD3ED23C5L,4UL,4UL,0xD3ED23C5L,1UL,0x0627E80AL,1UL,0xD3ED23C5L},{4UL,1UL,4UL,4294967295UL,0xE58ED0BDL,0xE58ED0BDL,4294967295UL,4UL}}; uint8_t l_37 = 0UL; int32_t *l_50 = &g_30[0]; int32_t **l_49 = &l_50; int32_t **l_84 = &g_73; int i, j; (*p_18) = (&p_16 != ((safe_rshift_func_int8_t_s_s(0x1EL, func_20(((*l_84) = func_33(((l_36[0][7] ^ (l_37 | (safe_mul_func_int16_t_s_s(((0x33933B839BF5BF81LL & (((((safe_div_func_uint32_t_u_u((((safe_unary_minus_func_int8_t_s(((-9L) == (g_26[5] > func_20(((*l_49) = func_43(((void*)0 == &p_16), l_37, p_18, l_36[0][2], p_16))))))) == 0UL) , 0x19F88DD0L), l_36[1][1])) & g_26[3]) , 0x0ECF58A4L) & p_16) , g_30[0])) >= 0xCFB11589A458230BLL), g_26[4])))) <= g_9[6]), p_17))))) , &l_37)); return (*g_73); } /* ------------------------------------------ */ /* * reads : g_9 g_23 g_30 * writes: g_23 g_30 */ static uint8_t func_20(int32_t * const p_21) { /* block id: 5 */ uint32_t l_24 = 1UL; (*p_21) ^= g_9[9]; return l_24; } /* ------------------------------------------ */ /* * reads : g_23 g_30 g_71 g_72 g_73 g_77 g_83 * writes: g_23 g_73 g_79 g_83 g_30 */ static int32_t * const func_33(int64_t p_34, uint8_t p_35) { /* block id: 14 */ int32_t **l_75[4] = {(void*)0,(void*)0,(void*)0,(void*)0}; int32_t **l_76 = &g_73; int32_t l_78[3][6][9] = {{{(-3L),8L,(-1L),0x33086262L,0x0EF155D2L,0x2C7DCB21L,0x0EF155D2L,0x33086262L,(-1L)},{(-1L),(-1L),(-9L),0xF1CC5CA3L,0x9E6D5949L,(-3L),0x0EF155D2L,(-1L),1L},{0xB4E13384L,0x3F16A1EAL,(-5L),(-6L),1L,(-3L),(-3L),1L,(-6L)},{(-9L),(-3L),(-9L),0xFDC3C1A3L,0x2C7DCB21L,0x3F16A1EAL,8L,1L,0x9E6D5949L},{(-3L),(-5L),(-1L),0x9E6D5949L,8L,(-1L),(-6L),(-1L),8L},{0xFDC3C1A3L,(-6L),(-6L),0xFDC3C1A3L,(-5L),5L,(-1L),0x33086262L,8L}},{{0x33086262L,(-9L),0x0EF155D2L,(-6L),(-3L),0x9E6D5949L,0x2C7DCB21L,0x2C7DCB21L,0x9E6D5949L},{(-5L),0xF1CC5CA3L,0xFDC3C1A3L,0xF1CC5CA3L,(-5L),0x33086262L,(-9L),0x0EF155D2L,(-6L)},{(-5L),5L,(-1L),0x33086262L,8L,(-9L),1L,0x3F16A1EAL,1L},{0x33086262L,0x2C7DCB21L,0xB4E13384L,0xB4E13384L,0x2C7DCB21L,0x33086262L,(-3L),(-5L),(-1L)},{0xFDC3C1A3L,0x2C7DCB21L,0x3F16A1EAL,8L,1L,0x9E6D5949L,0xB4E13384L,0xF1CC5CA3L,0xF1CC5CA3L},{0x3F16A1EAL,0x9E6D5949L,(-5L),0xB4E13384L,(-5L),0x9E6D5949L,0x3F16A1EAL,0xFDC3C1A3L,0x33086262L}},{{1L,(-6L),(-5L),0x3F16A1EAL,0xB4E13384L,(-3L),5L,0x9E6D5949L,0x0EF155D2L},{0xFDC3C1A3L,1L,0x33086262L,0x9E6D5949L,0x9E6D5949L,0x33086262L,1L,0xFDC3C1A3L,0x18108949L},{(-3L),(-1L),0xFDC3C1A3L,0x9E6D5949L,(-9L),0x18108949L,8L,(-6L),(-3L)},{0x18108949L,0xF1CC5CA3L,(-3L),0x3F16A1EAL,(-3L),0x3F16A1EAL,(-3L),0xF1CC5CA3L,0x18108949L},{5L,0x3F16A1EAL,(-9L),0xB4E13384L,(-3L),8L,(-1L),0x33086262L,0x0EF155D2L},{(-6L),0x33086262L,0xB4E13384L,(-1L),(-9L),(-9L),(-1L),0xB4E13384L,0x33086262L}}}; int i, j, k; for (g_23 = 0; (g_23 != (-1)); g_23--) { /* block id: 17 */ int32_t *l_53 = &g_30[0]; int32_t ***l_74[2][8][4] = {{{(void*)0,&g_72,&g_72,(void*)0},{&g_72,(void*)0,&g_72,&g_72},{&g_72,&g_72,&g_72,&g_72},{(void*)0,&g_72,&g_72,&g_72},{&g_72,&g_72,&g_72,&g_72},{&g_72,(void*)0,&g_72,(void*)0},{&g_72,&g_72,&g_72,&g_72},{(void*)0,&g_72,&g_72,(void*)0}},{{&g_72,(void*)0,&g_72,&g_72},{&g_72,&g_72,&g_72,&g_72},{(void*)0,&g_72,&g_72,&g_72},{&g_72,&g_72,&g_72,&g_72},{&g_72,(void*)0,&g_72,(void*)0},{&g_72,&g_72,&g_72,&g_72},{(void*)0,&g_72,&g_72,(void*)0},{&g_72,(void*)0,&g_72,&g_72}}}; int8_t *l_80 = (void*)0; int8_t *l_81 = (void*)0; int8_t *l_82 = &g_83; int i, j, k; (*l_53) = (l_53 == (((safe_unary_minus_func_int8_t_s((safe_mod_func_int8_t_s_s(g_30[1], ((*l_82) ^= func_57((g_79 = (safe_mul_func_int16_t_s_s(p_35, ((*l_53) || (safe_mod_func_uint32_t_u_u(((func_66((*l_53), (g_71 , ((l_75[1] = g_72) != (l_76 = &g_73))), g_30[1], p_35) , p_34) || 0xFB8AAA841158A35CLL), l_78[0][3][7])))))), l_78[0][3][7], p_35, p_35)))))) , (**l_76)) , (*g_72))); } return (*l_76); } /* ------------------------------------------ */ /* * reads : g_30 * writes: g_30 */ static int32_t * func_43(uint16_t p_44, int32_t p_45, int32_t * p_46, uint32_t p_47, const int64_t p_48) { /* block id: 10 */ (*p_46) &= 0x20A048C8L; return p_46; } /* ------------------------------------------ */ /* * reads : * writes: */ static int8_t func_57(int16_t p_58, uint64_t p_59, int32_t p_60, uint32_t p_61) { /* block id: 28 */ return p_61; } /* ------------------------------------------ */ /* * reads : g_73 g_23 g_72 g_77 * writes: g_73 */ static const union U1 func_66(int32_t p_67, int32_t p_68, uint32_t p_69, int32_t p_70) { /* block id: 20 */ if (((*g_73) | 0xF6324B7CL)) { /* block id: 21 */ (*g_72) = (*g_72); } else { /* block id: 23 */ (*g_72) = (*g_72); } return g_77; } /************************ statistics ************************* XXX max struct depth: 0 breakdown: depth: 0, occurrence: 24 XXX total union variables: 2 XXX non-zero bitfields defined in structs: 0 XXX zero bitfields defined in structs: 0 XXX const bitfields defined in structs: 0 XXX volatile bitfields defined in structs: 0 XXX structs with bitfields in the program: 0 breakdown: XXX full-bitfields structs in the program: 0 breakdown: XXX times a bitfields struct's address is taken: 0 XXX times a bitfields struct on LHS: 0 XXX times a bitfields struct on RHS: 0 XXX times a single bitfield on LHS: 0 XXX times a single bitfield on RHS: 0 XXX max expression depth: 44 breakdown: depth: 1, occurrence: 24 depth: 2, occurrence: 3 depth: 6, occurrence: 1 depth: 8, occurrence: 1 depth: 9, occurrence: 1 depth: 24, occurrence: 1 depth: 31, occurrence: 1 depth: 44, occurrence: 1 XXX total number of pointers: 34 XXX times a variable address is taken: 33 XXX times a pointer is dereferenced on RHS: 11 breakdown: depth: 1, occurrence: 10 depth: 2, occurrence: 1 XXX times a pointer is dereferenced on LHS: 18 breakdown: depth: 1, occurrence: 17 depth: 2, occurrence: 1 XXX times a pointer is compared with null: 1 XXX times a pointer is compared with address of another variable: 0 XXX times a pointer is compared with another pointer: 2 XXX times a pointer is qualified to be dereferenced: 69 XXX max dereference level: 2 breakdown: level: 0, occurrence: 0 level: 1, occurrence: 52 level: 2, occurrence: 7 XXX number of pointers point to pointers: 8 XXX number of pointers point to scalars: 26 XXX number of pointers point to structs: 0 XXX percent of pointers has null in alias set: 23.5 XXX average alias set size: 1.15 XXX times a non-volatile is read: 93 XXX times a non-volatile is write: 46 XXX times a volatile is read: 3 XXX times read thru a pointer: 0 XXX times a volatile is write: 1 XXX times written thru a pointer: 0 XXX times a volatile is available for access: 9 XXX percentage of non-volatile access: 97.2 XXX forward jumps: 0 XXX backward jumps: 0 XXX stmts: 23 XXX max block depth: 1 breakdown: depth: 0, occurrence: 19 depth: 1, occurrence: 4 XXX percentage a fresh-made variable is used: 23.8 XXX percentage an existing variable is used: 76.2 FYI: the random generator makes assumptions about the integer size. See platform.info for more details. ********************* end of statistics **********************/ Reducing failing test case with `creduce`... ...searching for "error[E0600]: cannot apply unary operator `-` to type `u32`". ...and reducing with this script: #!/usr/bin/env bash set -eu /home/fitzgen/rust-bindgen/csmith-fuzzing/predicate.py --bindgen-args '--with-derive-partialeq --with-derive-eq --with-derive-partialord --with-derive-ord --with-derive-hash --with-derive-default -- -I/home/fitzgen/rust-bindgen/csmith-fuzzing' --expect-compile-fail --rustc-grep 'error\[E0600\]\:\ cannot\ apply\ unary\ operator\ \`\-\`\ to\ type\ \`u32\`' input-uij7lxep.h Running: ['creduce', '--n', '48', '/tmp/input-uij7lxep.h.predicate.sh', '/tmp/input-uij7lxep.h'] ===< 2211 >=== running 48 interestingness tests in parallel ===< pass_includes :: 0 >=== ===< pass_unifdef :: 0 >=== ===< pass_comments :: 0 >=== (27.9 %, 11585 bytes) ===< pass_blank :: 0 >=== (28.2 %, 11527 bytes) ===< pass_clang_binsrch :: replace-function-def-with-decl >=== (85.1 %, 2400 bytes) ===< pass_clang_binsrch :: remove-unused-function >=== (93.3 %, 1084 bytes) ===< pass_lines :: 0 >=== (93.2 %, 1087 bytes) (94.4 %, 898 bytes) (95.8 %, 671 bytes) (96.6 %, 553 bytes) (98.2 %, 294 bytes) (98.8 %, 186 bytes) (99.0 %, 156 bytes) (99.6 %, 69 bytes) ===< pass_lines :: 1 >=== (99.6 %, 70 bytes) (99.6 %, 69 bytes) ===< pass_lines :: 2 >=== (99.6 %, 70 bytes) (99.6 %, 69 bytes) ===< pass_lines :: 3 >=== (99.6 %, 70 bytes) (99.6 %, 69 bytes) ===< pass_lines :: 4 >=== (99.6 %, 70 bytes) (99.6 %, 69 bytes) ===< pass_lines :: 6 >=== (99.6 %, 70 bytes) (99.6 %, 69 bytes) ===< pass_lines :: 8 >=== (99.6 %, 70 bytes) (99.6 %, 69 bytes) ===< pass_lines :: 10 >=== (99.6 %, 70 bytes) (99.6 %, 69 bytes) ===< pass_clang_binsrch :: replace-function-def-with-decl >=== ===< pass_clang_binsrch :: remove-unused-function >=== ===< pass_clang :: remove-unused-function >=== ===< pass_balanced :: curly >=== ===< pass_balanced :: curly2 >=== ===< pass_balanced :: curly3 >=== ===< pass_balanced :: parens-to-zero >=== ===< pass_clang :: callexpr-to-value >=== ===< pass_clang :: replace-callexpr >=== ===< pass_clang :: simplify-callexpr >=== ===< pass_clang :: remove-unused-enum-member >=== ===< pass_clang :: remove-enum-member-value >=== ===< pass_clang_binsrch :: remove-unused-var >=== ===< pass_special :: a >=== ===< pass_special :: b >=== ===< pass_special :: c >=== ===< pass_include_includes :: 0 >=== ===< pass_ternary :: b >=== ===< pass_ternary :: c >=== ===< pass_balanced :: curly >=== (cache hit for /tmp/input-uij7lxep.h) ===< pass_balanced :: curly2 >=== (cache hit for /tmp/input-uij7lxep.h) ===< pass_balanced :: curly3 >=== (cache hit for /tmp/input-uij7lxep.h) ===< pass_balanced :: parens >=== ===< pass_balanced :: angles >=== ===< pass_balanced :: square >=== ===< pass_balanced :: curly-inside >=== ===< pass_balanced :: parens-inside >=== ===< pass_balanced :: angles-inside >=== ===< pass_balanced :: square-inside >=== ===< pass_balanced :: curly-only >=== ===< pass_balanced :: angles-only >=== ===< pass_balanced :: square-only >=== ===< pass_clang :: remove-namespace >=== ===< pass_clang :: aggregate-to-scalar >=== ===< pass_clang :: param-to-global >=== ===< pass_clang :: param-to-local >=== ===< pass_clang :: remove-nested-function >=== ===< pass_clang :: union-to-struct >=== ===< pass_clang :: return-void >=== ===< pass_clang :: simple-inliner >=== ===< pass_clang :: reduce-pointer-level >=== ===< pass_clang :: lift-assignment-expr >=== ===< pass_clang :: copy-propagation >=== ===< pass_clang :: callexpr-to-value >=== (cache hit for /tmp/input-uij7lxep.h) ===< pass_clang :: replace-callexpr >=== (cache hit for /tmp/input-uij7lxep.h) ===< pass_clang :: simplify-callexpr >=== (cache hit for /tmp/input-uij7lxep.h) ===< pass_clang :: remove-unused-function >=== (cache hit for /tmp/input-uij7lxep.h) ===< pass_clang :: remove-unused-enum-member >=== (cache hit for /tmp/input-uij7lxep.h) ===< pass_clang :: remove-enum-member-value >=== (cache hit for /tmp/input-uij7lxep.h) ===< pass_clang_binsrch :: remove-unused-var >=== (cache hit for /tmp/input-uij7lxep.h) ===< pass_clang :: simplify-if >=== ===< pass_clang :: reduce-array-dim >=== ===< pass_clang :: reduce-array-size >=== ===< pass_clang :: move-function-body >=== ===< pass_clang :: simplify-comma-expr >=== ===< pass_clang :: simplify-dependent-typedef >=== ===< pass_clang :: replace-simple-typedef >=== ===< pass_clang :: replace-dependent-typedef >=== ===< pass_clang :: replace-one-level-typedef-type >=== ===< pass_clang :: remove-unused-field >=== ===< pass_clang :: instantiate-template-type-param-to-int >=== ===< pass_clang :: instantiate-template-param >=== ===< pass_clang :: template-arg-to-int >=== ===< pass_clang :: template-non-type-arg-to-int >=== ===< pass_clang :: reduce-class-template-param >=== ===< pass_clang :: remove-trivial-base-template >=== ===< pass_clang :: class-template-to-class >=== ===< pass_clang :: remove-base-class >=== ===< pass_clang :: replace-derived-class >=== ===< pass_clang :: remove-unresolved-base >=== ===< pass_clang :: remove-ctor-initializer >=== ===< pass_clang :: replace-class-with-base-template-spec >=== ===< pass_clang :: simplify-nested-class >=== ===< pass_clang :: remove-unused-outer-class >=== ===< pass_clang :: empty-struct-to-int >=== ===< pass_clang :: remove-pointer >=== ===< pass_clang :: reduce-pointer-pairs >=== ===< pass_clang :: remove-array >=== ===< pass_clang :: remove-addr-taken >=== ===< pass_clang :: simplify-struct >=== ===< pass_clang :: replace-undefined-function >=== ===< pass_clang :: replace-array-index-var >=== ===< pass_clang :: replace-array-access-with-index >=== ===< pass_clang :: replace-dependent-name >=== ===< pass_clang :: simplify-recursive-template-instantiation >=== ===< pass_clang :: vector-to-array >=== ===< pass_lines :: 0 >=== (99.6 %, 70 bytes) (99.6 %, 69 bytes) ===< pass_lines :: 1 >=== (cache hit for /tmp/input-uij7lxep.h) ===< pass_lines :: 2 >=== (cache hit for /tmp/input-uij7lxep.h) ===< pass_lines :: 3 >=== (cache hit for /tmp/input-uij7lxep.h) ===< pass_lines :: 4 >=== (cache hit for /tmp/input-uij7lxep.h) ===< pass_lines :: 6 >=== (cache hit for /tmp/input-uij7lxep.h) ===< pass_lines :: 8 >=== (cache hit for /tmp/input-uij7lxep.h) ===< pass_lines :: 10 >=== (cache hit for /tmp/input-uij7lxep.h) ===< pass_unifdef :: 0 >=== ===< pass_comments :: 0 >=== ===< pass_special :: b >=== (cache hit for /tmp/input-uij7lxep.h) ===< pass_special :: c >=== (cache hit for /tmp/input-uij7lxep.h) ===< pass_indent :: regular >=== (99.6 %, 68 bytes) ===< pass_balanced :: parens-to-zero >=== ===< pass_clex :: rm-toks-1 >=== (99.6 %, 61 bytes) ===< pass_clex :: rm-toks-2 >=== ===< pass_clex :: rm-toks-3 >=== ===< pass_clex :: rm-toks-4 >=== ===< pass_clex :: rm-toks-5 >=== ===< pass_clex :: rm-toks-6 >=== ===< pass_clex :: rm-toks-7 >=== ===< pass_clex :: rm-toks-8 >=== ===< pass_clex :: rm-toks-9 >=== ===< pass_clex :: rm-toks-10 >=== ===< pass_clex :: rm-toks-11 >=== ===< pass_clex :: rm-toks-12 >=== ===< pass_clex :: rm-toks-13 >=== ===< pass_clex :: rm-toks-14 >=== ===< pass_clex :: rm-toks-15 >=== ===< pass_clex :: rm-toks-16 >=== ===< pass_clex :: rm-tok-pattern-4 >=== ===< pass_clang :: local-to-global >=== ===< pass_peep :: a >=== ===< pass_peep :: c >=== ===< pass_ints :: a >=== ===< pass_ints :: b >=== ===< pass_ints :: c >=== (99.6 %, 59 bytes) ===< pass_ints :: d >=== ===< pass_ints :: e >=== ===< pass_balanced :: parens-only >=== ===< pass_clex :: rename-toks >=== (99.7 %, 55 bytes) ===< pass_clex :: delete-string >=== ===< pass_clex :: define >=== Termination check: size was 16061; now 55 ===< pass_include_includes :: 0 >=== ===< pass_ternary :: b >=== ===< pass_ternary :: c >=== ===< pass_balanced :: curly >=== ===< pass_balanced :: curly2 >=== ===< pass_balanced :: curly3 >=== ===< pass_balanced :: parens >=== ===< pass_balanced :: angles >=== ===< pass_balanced :: square >=== ===< pass_balanced :: curly-inside >=== ===< pass_balanced :: parens-inside >=== ===< pass_balanced :: angles-inside >=== ===< pass_balanced :: square-inside >=== ===< pass_balanced :: curly-only >=== ===< pass_balanced :: angles-only >=== ===< pass_balanced :: square-only >=== ===< pass_clang :: remove-namespace >=== ===< pass_clang :: aggregate-to-scalar >=== ===< pass_clang :: param-to-global >=== ===< pass_clang :: param-to-local >=== ===< pass_clang :: remove-nested-function >=== ===< pass_clang :: union-to-struct >=== ===< pass_clang :: return-void >=== ===< pass_clang :: simple-inliner >=== ===< pass_clang :: reduce-pointer-level >=== ===< pass_clang :: lift-assignment-expr >=== ===< pass_clang :: copy-propagation >=== ===< pass_clang :: callexpr-to-value >=== ===< pass_clang :: replace-callexpr >=== ===< pass_clang :: simplify-callexpr >=== ===< pass_clang :: remove-unused-function >=== ===< pass_clang :: remove-unused-enum-member >=== ===< pass_clang :: remove-enum-member-value >=== ===< pass_clang_binsrch :: remove-unused-var >=== ===< pass_clang :: simplify-if >=== ===< pass_clang :: reduce-array-dim >=== ===< pass_clang :: reduce-array-size >=== ===< pass_clang :: move-function-body >=== ===< pass_clang :: simplify-comma-expr >=== ===< pass_clang :: simplify-dependent-typedef >=== ===< pass_clang :: replace-simple-typedef >=== ===< pass_clang :: replace-dependent-typedef >=== ===< pass_clang :: replace-one-level-typedef-type >=== ===< pass_clang :: remove-unused-field >=== ===< pass_clang :: instantiate-template-type-param-to-int >=== ===< pass_clang :: instantiate-template-param >=== ===< pass_clang :: template-arg-to-int >=== ===< pass_clang :: template-non-type-arg-to-int >=== ===< pass_clang :: reduce-class-template-param >=== ===< pass_clang :: remove-trivial-base-template >=== ===< pass_clang :: class-template-to-class >=== ===< pass_clang :: remove-base-class >=== ===< pass_clang :: replace-derived-class >=== ===< pass_clang :: remove-unresolved-base >=== ===< pass_clang :: remove-ctor-initializer >=== ===< pass_clang :: replace-class-with-base-template-spec >=== ===< pass_clang :: simplify-nested-class >=== ===< pass_clang :: remove-unused-outer-class >=== ===< pass_clang :: empty-struct-to-int >=== ===< pass_clang :: remove-pointer >=== ===< pass_clang :: reduce-pointer-pairs >=== ===< pass_clang :: remove-array >=== ===< pass_clang :: remove-addr-taken >=== ===< pass_clang :: simplify-struct >=== ===< pass_clang :: replace-undefined-function >=== ===< pass_clang :: replace-array-index-var >=== ===< pass_clang :: replace-array-access-with-index >=== ===< pass_clang :: replace-dependent-name >=== ===< pass_clang :: simplify-recursive-template-instantiation >=== ===< pass_clang :: vector-to-array >=== ===< pass_lines :: 0 >=== (99.7 %, 56 bytes) (99.7 %, 55 bytes) ===< pass_lines :: 1 >=== (99.7 %, 56 bytes) (99.7 %, 55 bytes) ===< pass_lines :: 2 >=== (99.7 %, 56 bytes) (99.7 %, 55 bytes) ===< pass_lines :: 3 >=== (99.7 %, 56 bytes) (99.7 %, 55 bytes) ===< pass_lines :: 4 >=== (99.7 %, 56 bytes) (99.7 %, 55 bytes) ===< pass_lines :: 6 >=== (99.7 %, 56 bytes) (99.7 %, 55 bytes) ===< pass_lines :: 8 >=== (99.7 %, 56 bytes) (99.7 %, 55 bytes) ===< pass_lines :: 10 >=== (99.7 %, 56 bytes) (99.7 %, 55 bytes) ===< pass_unifdef :: 0 >=== ===< pass_comments :: 0 >=== ===< pass_special :: b >=== ===< pass_special :: c >=== ===< pass_indent :: regular >=== ===< pass_balanced :: parens-to-zero >=== ===< pass_clex :: rm-toks-1 >=== ===< pass_clex :: rm-toks-2 >=== ===< pass_clex :: rm-toks-3 >=== ===< pass_clex :: rm-toks-4 >=== ===< pass_clex :: rm-toks-5 >=== ===< pass_clex :: rm-toks-6 >=== ===< pass_clex :: rm-toks-7 >=== ===< pass_clex :: rm-toks-8 >=== ===< pass_clex :: rm-toks-9 >=== ===< pass_clex :: rm-toks-10 >=== ===< pass_clex :: rm-toks-11 >=== ===< pass_clex :: rm-toks-12 >=== ===< pass_clex :: rm-toks-13 >=== ===< pass_clex :: rm-toks-14 >=== ===< pass_clex :: rm-toks-15 >=== ===< pass_clex :: rm-toks-16 >=== ===< pass_clex :: rm-tok-pattern-4 >=== ===< pass_clang :: local-to-global >=== ===< pass_peep :: a >=== ===< pass_peep :: c >=== ===< pass_ints :: a >=== ===< pass_ints :: b >=== ===< pass_ints :: c >=== ===< pass_ints :: d >=== ===< pass_ints :: e >=== ===< pass_balanced :: parens-only >=== ===< pass_clex :: rename-toks >=== ===< pass_clex :: delete-string >=== (cache hit for /tmp/input-uij7lxep.h) ===< pass_clex :: define >=== (cache hit for /tmp/input-uij7lxep.h) Termination check: size was 55; now 55 ===< pass_clang :: rename-fun >=== ===< pass_clang :: rename-param >=== ===< pass_clang :: rename-var >=== ===< pass_clang :: rename-class >=== ===< pass_clang :: rename-cxx-method >=== ===< pass_clang :: combine-global-var >=== ===< pass_clang :: combine-local-var >=== ===< pass_clang :: simplify-struct-union-decl >=== ===< pass_clang :: move-global-var >=== ===< pass_clang :: unify-function-decl >=== ===< pass_lines :: 0 >=== (cache hit for /tmp/input-uij7lxep.h) ===< pass_clex :: rename-toks >=== (cache hit for /tmp/input-uij7lxep.h) ===< pass_clex :: delete-string >=== (cache hit for /tmp/input-uij7lxep.h) ===< pass_indent :: final >=== ===================== done ==================== pass statistics: method pass_ints :: c worked 1 times and failed 0 times method pass_clex :: rm-toks-1 worked 1 times and failed 16 times method pass_blank :: 0 worked 1 times and failed 1 times method pass_indent :: regular worked 1 times and failed 0 times method pass_clang_binsrch :: remove-unused-function worked 1 times and failed 0 times method pass_clang_binsrch :: replace-function-def-with-decl worked 1 times and failed 0 times method pass_clex :: rename-toks worked 1 times and failed 4 times method pass_comments :: 0 worked 1 times and failed 0 times method pass_lines :: 6 worked 4 times and failed 10 times method pass_lines :: 10 worked 4 times and failed 10 times method pass_lines :: 1 worked 4 times and failed 10 times method pass_lines :: 2 worked 4 times and failed 10 times method pass_lines :: 8 worked 4 times and failed 10 times method pass_lines :: 4 worked 4 times and failed 10 times method pass_lines :: 3 worked 4 times and failed 10 times method pass_lines :: 0 worked 12 times and failed 27 times ******** /tmp/input-uij7lxep.h ******** #include "csmith.h" uint32_t a = 18446744073709551611; `creduce` reduced the failing test case to: -------------------- /tmp/input-uij7lxep.h -------------------- #include "csmith.h" uint32_t a = 18446744073709551611; ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! File this issue at https://github.com/rust-lang-nursery/rust-bindgen/issues/new ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! --------------- 8< --------------- 8< --------------- 8< --------------- This bug was found with `csmith` and `driver.py`. ### Input Header ```c #include "csmith.h" uint32_t a = 18446744073709551611; ``` ### `bindgen` Invocation ``` $ './predicate.py' '--bindgen-args' '--with-derive-partialeq --with-derive-eq --with-derive-partialord --with-derive-ord --with-derive-hash --with-derive-default -- -I/home/fitzgen/rust-bindgen/csmith-fuzzing' '/tmp/input-uij7lxep.h' ``` ### Actual Results <details> ``` Running: ['cargo', 'run', '--manifest-path', '/home/fitzgen/rust-bindgen/Cargo.toml', '--', '/tmp/input-uij7lxep.h', '-o', '/tmp/bindings-vyl0qlte.rs', '--with-derive-partialeq', '--with-derive-eq', '--with-derive-partialord', '--with-derive-ord', '--with-derive-hash', '--with-derive-default', '--', '-I/home/fitzgen/rust-bindgen/csmith-fuzzing'] Running: ['rustc', '--crate-type', 'lib', '--test', '-o', '/tmp/layout-tests-41kuqr8x', '/tmp/bindings-vyl0qlte.rs'] Error: running `rustc` on the emitted bindings failed +error[E0600]: cannot apply unary operator `-` to type `u32` + --> /tmp/bindings-vyl0qlte.rs:27:333 + | +27 | } pub const g_79 : :: std :: os :: raw :: c_ushort = 1 ; pub const g_83 : :: std :: os :: raw :: c_schar = -50 ; pub const g_86 : :: std :: os :: raw :: c_int = -417508947 ; pub const g_93 : :: std :: os :: raw :: c_int = -9 ; pub const g_122 : :: std :: os :: raw :: c_short = 1 ; pub const g_124 : :: std :: os :: raw :: c_uint = -5 ; extern "C" { + | ^^ + +error: aborting due to previous error + ``` </details> ### Expected Results `bindgen` emits bindings OK, then `rustc` compiles those bindings OK, then the compiled bindings' layout tests pass OK. --------------- 8< --------------- 8< --------------- 8< --------------- <3 <3 <3 Thank you! <3 <3 <3 </code></pre></details>
2 parents d5a5c50 + 1313995 commit 52fe951

File tree

3 files changed

+258
-37
lines changed

3 files changed

+258
-37
lines changed

csmith-fuzzing/README.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@ tests in the bindings fail, then we report an issue containing the test case!
1818

1919
## Prerequisites
2020

21-
Requires `python3`, `csmith` and `bindgen` to be in `$PATH`.
21+
Requires `python3`, `csmith`, and `creduce` to be in `$PATH`.
2222

23-
Many OS package managers have a `csmith` package:
23+
Many OS package managers have `csmith` and `creduce` packages:
2424

2525
```
26-
$ sudo apt install csmith
27-
$ brew install csmith
26+
$ sudo apt install csmith creduce
27+
$ brew install csmith creduce
2828
$ # Etc...
2929
```
3030

csmith-fuzzing/driver.py

+244-29
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,44 @@
11
#!/usr/bin/env python3
22

3-
import os, sys
3+
import argparse
4+
import os
5+
import re
6+
import shlex
7+
import sys
48
from subprocess import run, SubprocessError, DEVNULL, PIPE
59
from tempfile import NamedTemporaryFile
610

7-
csmith_command = [
8-
"csmith",
9-
"--no-checksum",
10-
"--nomain",
11-
"--max-block-size", "1",
12-
"--max-block-depth", "1",
13-
]
11+
DESC = """
1412
15-
def cat(path, title=None):
16-
if not title:
17-
title = path
18-
print("-------------------- {} --------------------".format(title))
19-
run(["cat", path])
13+
A `csmith` fuzzing driver for `bindgen`.
2014
21-
def run_logged(cmd):
22-
with NamedTemporaryFile() as stdout, NamedTemporaryFile() as stderr:
23-
result = run(cmd, stdin=DEVNULL, stdout=stdout, stderr=stderr)
24-
if result.returncode != 0:
25-
print()
26-
print("Error: '{}' exited with code {}".format(" ".join(cmd), result.returncode))
27-
cat(stdout.name, title="stdout")
28-
cat(stdout.name, title="stderr")
29-
return result
15+
Generates random C source files with `csmith` and then passes them to `bindgen`
16+
(via `predicate.py`). If `bindgen` can't emit bindings, `rustc` can't compile
17+
those bindings, or the compiled bindings' layout tests fail, then the driver has
18+
found a bug, and will report the problematic test case to you.
19+
20+
"""
21+
22+
parser = argparse.ArgumentParser(
23+
formatter_class=argparse.RawDescriptionHelpFormatter,
24+
description=DESC.strip())
25+
26+
parser.add_argument(
27+
"--keep-going",
28+
action="store_true",
29+
help="Do not stop after finding a test case that exhibits a bug in `bindgen`. Instead, keep going.")
30+
31+
CSMITH_ARGS="\
32+
--no-checksum \
33+
--nomain \
34+
--max-block-size 1 \
35+
--max-block-depth 1"
36+
37+
parser.add_argument(
38+
"--csmith-args",
39+
type=str,
40+
default=CSMITH_ARGS,
41+
help="Pass this argument string to `csmith`. By default, very small functions are generated.")
3042

3143
BINDGEN_ARGS = "--with-derive-partialeq \
3244
--with-derive-eq \
@@ -35,31 +47,234 @@ def run_logged(cmd):
3547
--with-derive-hash \
3648
--with-derive-default"
3749

50+
parser.add_argument(
51+
"--bindgen-args",
52+
type=str,
53+
default=BINDGEN_ARGS,
54+
help="Pass this argument string to `bindgen`. By default, all traits are derived.")
55+
56+
parser.add_argument(
57+
"--no-creduce",
58+
action="store_false",
59+
dest="creduce",
60+
help="Do not run `creduce` on any buggy test case(s) discovered.")
61+
62+
################################################################################
63+
64+
def cat(path, title=None):
65+
if not title:
66+
title = path
67+
print("-------------------- {} --------------------".format(title))
68+
print()
69+
print()
70+
run(["cat", path])
71+
72+
def decode(f):
73+
return f.decode(encoding="utf-8", errors="ignore")
74+
75+
def run_logged(cmd):
76+
result = run(cmd, stdin=DEVNULL, stdout=PIPE, stderr=PIPE)
77+
result.stdout = decode(result.stdout)
78+
result.stderr = decode(result.stderr)
79+
if result.returncode != 0:
80+
print()
81+
print()
82+
print("Error: {} exited with code {}".format(cmd, result.returncode))
83+
print()
84+
print()
85+
for line in result.stdout.splitlines():
86+
sys.stdout.write("+")
87+
sys.stdout.write(line)
88+
sys.stdout.write("\n")
89+
for line in result.stderr.splitlines():
90+
sys.stderr.write("+")
91+
sys.stderr.write(line)
92+
sys.stderr.write("\n")
93+
return result
94+
3895
def main():
39-
print("Fuzzing `bindgen` with C-Smith...\n")
96+
os.environ["RUST_BACKTRACE"] = "full"
97+
args = parser.parse_args()
98+
99+
bindgen_args = args.bindgen_args
100+
if bindgen_args.find(" -- ") == -1:
101+
bindgen_args = bindgen_args + " -- "
102+
bindgen_args = bindgen_args + " -I{}".format(os.path.abspath(os.path.dirname(sys.argv[0])))
103+
args.bindgen_args = bindgen_args
104+
105+
print()
106+
print()
107+
print("Fuzzing `bindgen` with C-Smith...")
108+
print()
109+
print()
40110

41111
iterations = 0
42112
while True:
43113
print("\rIteration: {}".format(iterations), end="", flush=True)
114+
iterations += 1
44115

45116
input = NamedTemporaryFile(delete=False, prefix="input-", suffix=".h")
46117
input.close()
47-
result = run_logged(csmith_command + ["-o", input.name])
118+
result = run_logged(["csmith", "-o", input.name] + shlex.split(args.csmith_args))
48119
if result.returncode != 0:
49120
exit(1)
50121

51-
result = run_logged([
122+
predicate_command = [
52123
"./predicate.py",
53124
"--bindgen-args",
54-
"{} -- -I{}".format(BINDGEN_ARGS, os.path.abspath(os.path.dirname(sys.argv[0]))),
125+
args.bindgen_args,
55126
input.name
56-
])
127+
]
128+
result = run_logged(predicate_command)
129+
57130
if result.returncode != 0:
58-
cat(input.name)
131+
print()
132+
print()
133+
cat(input.name, title="Failing test case: {}".format(input.name))
134+
print()
135+
print()
136+
137+
if args.creduce:
138+
creduce(args, input.name, result)
139+
140+
print_issue_template(args, input.name, predicate_command, result)
141+
142+
if args.keep_going:
143+
continue
59144
exit(1)
60145

61146
os.remove(input.name)
62-
iterations += 1
147+
148+
RUSTC_ERROR_REGEX = re.compile(r".*(error\[.*].*)")
149+
LAYOUT_TEST_FAILURE = re.compile(r".*(test bindgen_test_layout_.* \.\.\. FAILED)")
150+
151+
def creduce(args, failing_test_case, result):
152+
print()
153+
print()
154+
print("Reducing failing test case with `creduce`...")
155+
156+
match = re.search(RUSTC_ERROR_REGEX, result.stderr)
157+
if match:
158+
error_msg = match.group(1)
159+
print("...searching for \"{}\".".format(error_msg))
160+
return creduce_with_predicate_flags(
161+
args,
162+
failing_test_case,
163+
"--bindgen-args '{}' --expect-compile-fail --rustc-grep '{}'".format(
164+
args.bindgen_args,
165+
re.escape(error_msg)
166+
)
167+
)
168+
169+
match = re.search(LAYOUT_TEST_FAILURE, result.stdout)
170+
if match:
171+
layout_failure = match.group(1)
172+
struct_name = layout_failure[len("test bindgen_test_layout_"):layout_failure.rindex(" ... FAILED")]
173+
print("...searching for \"{}\".".format(layout_failure))
174+
return creduce_with_predicate_flags(
175+
args,
176+
failing_test_case,
177+
"--bindgen-args '{}' --expect-layout-tests-fail --bindings-grep '{}' --layout-tests-grep '{}'".format(
178+
args.bindgen_args,
179+
re.escape(struct_name),
180+
re.escape(layout_failure)
181+
)
182+
)
183+
184+
print("...nevermind, don't know how to `creduce` this bug. Skipping.")
185+
186+
def creduce_with_predicate_flags(args, failing_test_case, predicate_flags):
187+
predicate = """
188+
#!/usr/bin/env bash
189+
set -eu
190+
{} {} {}
191+
""".format(
192+
os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), "predicate.py")),
193+
predicate_flags,
194+
os.path.basename(failing_test_case)
195+
)
196+
197+
print("...and reducing with this script:")
198+
print()
199+
print()
200+
print(predicate)
201+
print()
202+
print()
203+
204+
predicate_path = failing_test_case + ".predicate.sh"
205+
with open(predicate_path, "w") as p:
206+
p.write(predicate)
207+
os.chmod(predicate_path, 0o755)
208+
209+
creduce_command = ["creduce", "--n", str(os.cpu_count()), predicate_path, failing_test_case]
210+
print("Running:", creduce_command)
211+
result = run(creduce_command)
212+
if result.returncode == 0:
213+
print()
214+
print()
215+
print("`creduce` reduced the failing test case to:")
216+
print()
217+
print()
218+
cat(failing_test_case)
219+
print()
220+
print()
221+
else:
222+
print()
223+
print()
224+
print("`creduce` failed!")
225+
if not args.keep_going:
226+
sys.exit(1)
227+
228+
def print_issue_template(args, failing_test_case, predicate_command, result):
229+
test_case_contents = None
230+
with open(failing_test_case, "r") as f:
231+
test_case_contents = f.read()
232+
233+
print("""
234+
235+
! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !
236+
! File this issue at https://github.com/rust-lang-nursery/rust-bindgen/issues/new !
237+
! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !
238+
239+
--------------- 8< --------------- 8< --------------- 8< ---------------
240+
241+
This bug was found with `csmith` and `driver.py`.
242+
243+
### Input Header
244+
245+
```c
246+
{}
247+
```
248+
249+
### `bindgen` Invocation
250+
251+
```
252+
$ {}
253+
```
254+
255+
### Actual Results
256+
257+
<details>
258+
259+
```
260+
{}
261+
```
262+
263+
</details>
264+
265+
### Expected Results
266+
267+
`bindgen` emits bindings OK, then `rustc` compiles those bindings OK, then the
268+
compiled bindings' layout tests pass OK.
269+
270+
--------------- 8< --------------- 8< --------------- 8< ---------------
271+
272+
<3 <3 <3 Thank you! <3 <3 <3
273+
""".format(
274+
test_case_contents,
275+
" ".join(map(lambda s: "'{}'".format(s), predicate_command)),
276+
result.stdout + result.stderr
277+
))
63278

64279
if __name__ == "__main__":
65280
try:

csmith-fuzzing/predicate.py

+10-4
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,16 @@ def exit_1(msg, child=None):
110110
print(msg)
111111

112112
if child:
113-
print("---------- stdout ----------------------------------------------")
114-
print(decode(child.stdout))
115-
print("---------- stderr ----------------------------------------------")
116-
print(decode(child.stderr))
113+
stdout = decode(child.stdout)
114+
for line in stdout.splitlines():
115+
sys.stdout.write("+")
116+
sys.stdout.write(line)
117+
sys.stdout.write("\n")
118+
stderr = decode(child.stderr)
119+
for line in stderr.splitlines():
120+
sys.stderr.write("+")
121+
sys.stderr.write(line)
122+
sys.stderr.write("\n")
117123

118124
raise ExitOne()
119125

0 commit comments

Comments
 (0)