diff options
author | Patrik Nyblom <[email protected]> | 2013-08-14 17:09:13 +0200 |
---|---|---|
committer | Patrik Nyblom <[email protected]> | 2013-08-15 18:15:35 +0200 |
commit | 52cb62b7930d9c7b9e04a210ff6b02946f27ae79 (patch) | |
tree | b701c64d2e3eb5b259c9102e4e741f190d2e530d | |
parent | 925d69c56d376d1e2371cd2236c981bc97ccb706 (diff) | |
download | otp-52cb62b7930d9c7b9e04a210ff6b02946f27ae79.tar.gz otp-52cb62b7930d9c7b9e04a210ff6b02946f27ae79.tar.bz2 otp-52cb62b7930d9c7b9e04a210ff6b02946f27ae79.zip |
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.
-rw-r--r-- | erts/emulator/beam/erl_bif_re.c | 30 |
1 files changed, 18 insertions, 12 deletions
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;i<top;++i) { - if (last == NULL || !has_dupnames || strcmp(last+2,nametable+2)) { + if (last == NULL || !has_dupnames || strcmp((char *) last+2,(char *) nametable+2)) { ASSERT(ri->num_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<top;++i) { - if (last == NULL || !has_dupnames || strcmp(last+2,name+2)) { + if (last == NULL || !has_dupnames || strcmp((char *) last+2, + (char *) name+2)) { ++num_names; } last = name; @@ -1478,8 +1483,9 @@ re_inspect_2(BIF_ALIST_2) name = nametable; j = 0; for(i=0;i<top;++i) { - if (last == NULL || !has_dupnames || strcmp(last+2,name+2)) { - tmp_vec[j++] = new_binary(BIF_P, (byte *) name+2, strlen(name+2)); + if (last == NULL || !has_dupnames || strcmp((char *) last+2, + (char *) name+2)) { + tmp_vec[j++] = new_binary(BIF_P, (byte *) name+2, strlen((char *) name+2)); } last = name; name += entrysize; |