From 52cb62b7930d9c7b9e04a210ff6b02946f27ae79 Mon Sep 17 00:00:00 2001 From: Patrik Nyblom Date: Wed, 14 Aug 2013 17:09:13 +0200 Subject: Workaround TR gnu/181328, GCC 4.2.1 20070831 on FreeBSD 9.1 The bug manifests so that initialization of an automatic variable happens after a pointer to the variable is dereferenced, causing build_exec_return to take the wrong branch by default. The bug is verified to happen even outside the VM and is reported to FreeBSD as trouble ID gnu/181328. The workaround is a slight code rewrite which is optimized differently. Also removed two warnings about dereferencing type-punned pointers, which did not affect the bug. --- erts/emulator/beam/erl_bif_re.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) (limited to 'erts') diff --git a/erts/emulator/beam/erl_bif_re.c b/erts/emulator/beam/erl_bif_re.c index 796fd301ad..99c31738a5 100644 --- a/erts/emulator/beam/erl_bif_re.c +++ b/erts/emulator/beam/erl_bif_re.c @@ -628,11 +628,15 @@ static Eterm build_exec_return(Process *p, int rc, RestartContext *restartp, Ete res = am_nomatch; } } else { - ReturnInfo *ri = restartp->ret_info; + ReturnInfo *ri; ReturnInfo defri = {RetIndex,0,{0}}; - if (ri == NULL) { + + if (restartp->ret_info == NULL) { ri = &defri; + } else { + ri = restartp->ret_info; } + if (ri->type == RetNone) { res = am_match; } else if (ri->type == RetIndex){ @@ -923,7 +927,7 @@ build_capture(Eterm capture_spec[CAPSPEC_SIZE], const pcre *code) { int rc,i,top; int entrysize; - char *nametable, *last = NULL; + unsigned char *nametable, *last = NULL; int has_dupnames; unsigned long options; @@ -938,13 +942,13 @@ build_capture(Eterm capture_spec[CAPSPEC_SIZE], const pcre *code) } if (erts_pcre_fullinfo(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize) != 0) goto error; - if (erts_pcre_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, (unsigned char **) &nametable) != 0) + if (erts_pcre_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, &nametable) != 0) goto error; has_dupnames = ((options & PCRE_DUPNAMES) != 0); for(i=0;inum_spec >= 0); ++(ri->num_spec); if(ri->num_spec > sallocated) { @@ -955,7 +959,7 @@ build_capture(Eterm capture_spec[CAPSPEC_SIZE], const pcre *code) /* This could be more effective, we actually have the names and could fill in the vector immediately. Now we lookup the name again. */ - build_one_capture(code,&ri,&sallocated,has_dupnames,nametable+2); + build_one_capture(code,&ri,&sallocated,has_dupnames,(char *) nametable+2); } else { ri->v[ri->num_spec - 1] = PICK_INDEX(nametable); } @@ -1236,7 +1240,7 @@ re_run(Process *p, Eterm arg1, Eterm arg2, Eterm arg3) BIF_ERROR(p,BADARG); } } - + /* Optimized - if already in binary off heap, keep that and avoid copying, also binary returns can be sub binaries in that case */ @@ -1398,7 +1402,7 @@ re_inspect_2(BIF_ALIST_2) Eterm *tp,*tmp_vec,*hp; int i,top,j; int entrysize; - char *nametable, *last,*name; + unsigned char *nametable, *last,*name; int has_dupnames; unsigned long options; int num_names; @@ -1455,7 +1459,7 @@ re_inspect_2(BIF_ALIST_2) #ifdef DEBUG infores = #endif - erts_pcre_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, (unsigned char **) &nametable); + erts_pcre_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, &nametable); ASSERT(infores == 0); @@ -1465,7 +1469,8 @@ re_inspect_2(BIF_ALIST_2) last = NULL; name = nametable; for(i=0;i