@@ -167,8 +167,7 @@ def can_do_standalone(self):
167167 not self .get_setting ('MINIMAL_RUNTIME' ) and \
168168 not self .get_setting ('SAFE_HEAP' ) and \
169169 not self .get_setting ('MEMORY64' ) and \
170- '-fsanitize=address' not in self .emcc_args and \
171- '-fsanitize=leak' not in self .emcc_args
170+ not any (a .startswith ('-fsanitize=' ) for a in self .emcc_args )
172171
173172
174173def also_with_wasmfs (func ):
@@ -290,6 +289,36 @@ def decorated(self, *args, **kwargs):
290289 return decorator
291290
292291
292+ def no_ubsan (note ):
293+ assert not callable (note )
294+
295+ def decorator (f ):
296+ assert callable (f )
297+
298+ @wraps (f )
299+ def decorated (self , * args , ** kwargs ):
300+ if '-fsanitize=undefined' in self .emcc_args :
301+ self .skipTest (note )
302+ f (self , * args , ** kwargs )
303+ return decorated
304+ return decorator
305+
306+
307+ def no_sanitize (note ):
308+ assert not callable (note )
309+
310+ def decorator (f ):
311+ assert callable (f )
312+
313+ @wraps (f )
314+ def decorated (self , * args , ** kwargs ):
315+ if any (a .startswith ('-fsanitize=' ) for a in self .emcc_args ):
316+ self .skipTest (note )
317+ f (self , * args , ** kwargs )
318+ return decorated
319+ return decorator
320+
321+
293322def no_memory64 (note ):
294323 assert not callable (note )
295324
@@ -465,6 +494,7 @@ def test_i64_umul(self):
465494 self .do_core_test ('test_i64_umul.c' )
466495
467496 @also_with_standalone_wasm ()
497+ @no_ubsan ('contains UB' )
468498 def test_i64_precise (self ):
469499 self .do_core_test ('test_i64_precise.c' )
470500
@@ -660,13 +690,12 @@ def test_align64(self):
660690 double y;
661691 };
662692
663- int main(int argc, char **argv)
664- {
693+ int main(int argc, char **argv) {
665694 int base = argc-1;
666- Object *o = NULL ;
695+ Object o[10] ;
667696 printf("%zu,%zu\n", sizeof(Object), sizeof(Principal));
668- printf("%ld,%ld,%ld,%ld\n", (long)&o[base].type, (long)&o[base].intg, (long)&o[base].real, (long)&o[base].name);
669- printf("%ld,%ld,%ld,%ld\n", (long)&o[base+1].type, (long)&o[base+1].intg, (long)&o[base+1].real, (long)&o[base+1].name);
697+ printf("%ld,%ld,%ld,%ld\n", (long)&o[base].type - (long)o , (long)&o[base].intg - (long)o , (long)&o[base].real - (long)o , (long)&o[base].name - (long)o );
698+ printf("%ld,%ld,%ld,%ld\n", (long)&o[base+1].type - (long)o , (long)&o[base+1].intg - (long)o , (long)&o[base+1].real - (long)o , (long)&o[base+1].name - (long)o );
670699 Principal p, q;
671700 p.x = p.y = q.x = q.y = 0;
672701 p.a.type = A;
@@ -897,8 +926,7 @@ def test_stack_placement(self):
897926 self .set_setting ('GLOBAL_BASE' , 102400 )
898927 self .do_core_test ('test_stack_placement.c' )
899928
900- @no_asan ('asan does not support main modules' )
901- @no_lsan ('asan does not support main modules' )
929+ @no_sanitize ('sanitizers do not yet support dynamic linking' )
902930 @no_wasm2js ('MAIN_MODULE support' )
903931 def test_stack_placement_pic (self ):
904932 self .set_setting ('TOTAL_STACK' , 1024 )
@@ -980,6 +1008,7 @@ def test_emmalloc_usable_size(self, *args):
9801008 @no_optimize ('output is sensitive to optimization flags, so only test unoptimized builds' )
9811009 @no_asan ('ASan does not support custom memory allocators' )
9821010 @no_lsan ('LSan does not support custom memory allocators' )
1011+ @no_ubsan ('UBSan changes memory consumption' )
9831012 def test_emmalloc_memory_statistics (self , * args ):
9841013
9851014 self .set_setting ('MALLOC' , 'emmalloc' )
@@ -2237,6 +2266,7 @@ def test_memorygrowth_linear_step(self):
22372266 self .emcc_args += ['-sALLOW_MEMORY_GROWTH' , '-sTOTAL_STACK=1Mb' , '-sINITIAL_MEMORY=64Mb' , '-sMAXIMUM_MEMORY=130Mb' , '-sMEMORY_GROWTH_LINEAR_STEP=1Mb' ]
22382267 self .do_core_test ('test_memorygrowth_memory_growth_step.c' )
22392268
2269+ @no_ubsan ('UBSan seems to effect the precise memory usage' )
22402270 def test_memorygrowth_geometric_step (self ):
22412271 if self .has_changed_setting ('ALLOW_MEMORY_GROWTH' ):
22422272 self .skipTest ('test needs to modify memory growth' )
@@ -2332,12 +2362,14 @@ def test_biggerswitch(self):
2332236259899: 598995989959899
23332363Success!''' )
23342364
2365+ @no_ubsan ('local count too large for VMs' )
23352366 def test_indirectbr (self ):
23362367 self .emcc_args = [x for x in self .emcc_args if x != '-g' ]
23372368
23382369 self .do_core_test ('test_indirectbr.c' )
23392370
23402371 @no_asan ('local count too large for VMs' )
2372+ @no_ubsan ('local count too large for VMs' )
23412373 @no_wasm2js ('extremely deep nesting, hits stack limit on some VMs' )
23422374 def test_indirectbr_many (self ):
23432375 self .do_core_test ('test_indirectbr_many.c' )
@@ -2348,26 +2380,24 @@ def test_pack(self):
23482380 #include <string.h>
23492381
23502382 #pragma pack(push,1)
2351- typedef struct header
2352- {
2383+ typedef struct header {
23532384 unsigned char id;
23542385 unsigned short colour;
23552386 unsigned char desc;
23562387 } header;
23572388 #pragma pack(pop)
23582389
2359- typedef struct fatheader
2360- {
2390+ typedef struct fatheader {
23612391 unsigned char id;
23622392 unsigned short colour;
23632393 unsigned char desc;
23642394 } fatheader;
23652395
23662396 int main( int argc, const char *argv[] ) {
2367- header h, *ph = 0 ;
2368- fatheader fh, * pfh = 0 ;
2369- printf("*%zu,%ld,%ld*\\ n", sizeof(header), (long)((long)&h. desc - (long)&h. id), (long)(&ph[1])-(long)(&ph[0]));
2370- printf("*%zu,%ld,%ld*\\ n", sizeof(fatheader), (long)((long)&fh. desc - (long)&fh. id), (long)(&pfh[1])-(long)(&pfh[0]));
2397+ header ph[2] ;
2398+ fatheader pfh[2] ;
2399+ printf("*%zu,%ld,%ld*\\ n", sizeof(header), offsetof(header, desc) - offsetof(header, id), (long)(&ph[1])-(long)(&ph[0]));
2400+ printf("*%zu,%ld,%ld*\\ n", sizeof(fatheader), offsetof(fatheader, desc) - offsetof(fatheader, id), (long)(&pfh[1])-(long)(&pfh[0]));
23712401 return 0;
23722402 }
23732403 '''
@@ -2790,7 +2820,7 @@ def test_stackAlloc(self):
27902820 self .do_core_test ('stackAlloc.cpp' )
27912821
27922822 def test_nestedstructs (self ):
2793- src = '''
2823+ src = r '''
27942824 #include <stdio.h>
27952825 #include "emscripten.h"
27962826
@@ -2817,16 +2847,34 @@ def test_nestedstructs(self):
28172847
28182848 struct hashtable : hashset {
28192849 hashtable() {
2820- base *b = NULL ;
2821- entry *e = NULL ;
2822- chain *c = NULL ;
2823- printf("*%zu,%ld,%ld,%ld,%ld,%ld|%zu,%ld,%ld,%ld,%ld,%ld,%ld,%ld|%zu,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld*\\ n",
2850+ base b ;
2851+ entry e ;
2852+ chain c ;
2853+ printf("*%zu,%ld,%ld,%ld,%ld,%ld|%zu,%ld,%ld,%ld,%ld,%ld,%ld,%ld|%zu,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld*\n",
28242854 sizeof(base),
2825- long(&(b->x)), long(&(b->y)), long(&(b->a)), long(&(b->b)), long(&(b->c)),
2855+ long(&b.x) - long(&b),
2856+ long(&b.y) - long(&b),
2857+ long(&b.a) - long(&b),
2858+ long(&b.b) - long(&b),
2859+ long(&b.c) - long(&b),
28262860 sizeof(hashtableentry),
2827- long(&(e->key)), long(&(e->data)), long(&(e->data.x)), long(&(e->data.y)), long(&(e->data.a)), long(&(e->data.b)), long(&(e->data.c)),
2861+ long(&e.key) - long(&e),
2862+ long(&e.data) - long(&e),
2863+ long(&e.data.x) - long(&e),
2864+ long(&e.data.y) - long(&e),
2865+ long(&e.data.a) - long(&e),
2866+ long(&e.data.b) - long(&e),
2867+ long(&e.data.c) - long(&e),
28282868 sizeof(hashset::chain),
2829- long(&(c->elem)), long(&(c->next)), long(&(c->elem.key)), long(&(c->elem.data)), long(&(c->elem.data.x)), long(&(c->elem.data.y)), long(&(c->elem.data.a)), long(&(c->elem.data.b)), long(&(c->elem.data.c))
2869+ long(&c.elem) - long(&c),
2870+ long(&c.next) - long(&c),
2871+ long(&c.elem.key) - long(&c),
2872+ long(&c.elem.data) - long(&c),
2873+ long(&c.elem.data.x) - long(&c),
2874+ long(&c.elem.data.y) - long(&c),
2875+ long(&c.elem.data.a) - long(&c),
2876+ long(&c.elem.data.b) - long(&c),
2877+ long(&c.elem.data.c) - long(&c)
28302878 );
28312879 }
28322880 };
@@ -2849,19 +2897,23 @@ def test_nestedstructs(self):
28492897
28502898 // Part 2 - the char[] should be compressed, BUT have a padding space at the end so the next
28512899 // one is aligned properly. Also handle char; char; etc. properly.
2852- B *b = NULL;
2853- printf("*%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%zu*\\ n", long(b), long(&(b->buffer)), long(&(b->buffer[0])), long(&(b->buffer[1])), long(&(b->buffer[2])),
2854- long(&(b->last)), long(&(b->laster)), long(&(b->laster2)), sizeof(B));
2900+ B b;
2901+ printf("*%ld,%ld,%ld,%ld,%ld,%ld,%ld,%zu*\n", long(&b.buffer) - long(&b),
2902+ long(&b.buffer[0]) - long(&b),
2903+ long(&b.buffer[1]) - long(&b),
2904+ long(&b.buffer[2]) - long(&b),
2905+ long(&b.last) - long(&b),
2906+ long(&b.laster) - long(&b),
2907+ long(&b.laster2) - long(&b),
2908+ sizeof(B));
28552909
28562910 // Part 3 - bitfields, and small structures
2857- Bits *b2 = NULL;
2858- printf("*%zu*\\ n", sizeof(Bits));
2859-
2911+ printf("*%zu*\n", sizeof(Bits));
28602912 return 0;
28612913 }
28622914 '''
28632915 # Bloated memory; same layout as C/C++
2864- self .do_run (src , '*16,0,4,8,8,12|20,0,4,4,8,12,12,16|24,0,20,0,4,4,8,12,12,16*\n *0,0,0, 1,2,64,68,69,72*\n *2*' )
2916+ self .do_run (src , '*16,0,4,8,8,12|20,0,4,4,8,12,12,16|24,0,20,0,4,4,8,12,12,16*\n *0,0,1,2,64,68,69,72*\n *2*' )
28652917
28662918 def prep_dlfcn_main (self ):
28672919 self .set_setting ('NODERAWFS' )
@@ -6311,6 +6363,7 @@ def test_neon_wasm_simd(self):
63116363 @wasm_simd
63126364 @requires_native_clang
63136365 @no_safe_heap ('has unaligned 64-bit operations in wasm' )
6366+ @no_ubsan ('test contains UB' )
63146367 def test_sse1 (self ):
63156368 src = test_file ('sse/test_sse1.cpp' )
63166369 self .run_process ([shared .CLANG_CXX , src , '-msse' , '-o' , 'test_sse1' , '-D_CRT_SECURE_NO_WARNINGS=1' ] + clang_native .get_clang_native_args (), stdout = PIPE )
@@ -8038,8 +8091,7 @@ def verify_broken(args=['0']):
80388091 verify_broken ()
80398092
80408093 # Test basic wasm2js functionality in all core compilation modes.
8041- @no_asan ('no wasm2js support yet in asan' )
8042- @no_lsan ('no wasm2js support yet in lsan' )
8094+ @no_sanitize ('no wasm2js support yet in sanitizers' )
80438095 def test_wasm2js (self ):
80448096 if not self .is_wasm ():
80458097 self .skipTest ('redundant to test wasm2js in wasm2js* mode' )
@@ -8054,8 +8106,7 @@ def test_wasm2js(self):
80548106 else :
80558107 self .assertNotExists ('test_hello_world.js.mem' )
80568108
8057- @no_asan ('no wasm2js support yet in asan' )
8058- @no_lsan ('no wasm2js support yet in lsan' )
8109+ @no_sanitize ('no wasm2js support yet in sanitizers' )
80598110 def test_maybe_wasm2js (self ):
80608111 if not self .is_wasm ():
80618112 self .skipTest ('redundant to test wasm2js in wasm2js* mode' )
@@ -9235,6 +9286,7 @@ def setUp(self):
92359286# Add DEFAULT_TO_CXX=0
92369287strict = make_run ('strict' , emcc_args = [], settings = {'STRICT' : 1 })
92379288
9289+ ubsan = make_run ('ubsan' , emcc_args = ['-fsanitize=undefined' , '--profiling' ])
92389290lsan = make_run ('lsan' , emcc_args = ['-fsanitize=leak' , '--profiling' ], settings = {'ALLOW_MEMORY_GROWTH' : 1 })
92399291asan = make_run ('asan' , emcc_args = ['-fsanitize=address' , '--profiling' ], settings = {'ALLOW_MEMORY_GROWTH' : 1 })
92409292asani = make_run ('asani' , emcc_args = ['-fsanitize=address' , '--profiling' , '--pre-js' , os .path .join (os .path .dirname (__file__ ), 'asan-no-leak.js' )],
0 commit comments