ThomasDickey / original-mawk

bug-reports for mawk (originally on GoogleCode)
http://invisible-island.net/mawk/mawk.html
17 stars 2 forks source link

Random segmentation fault with -W options #68

Closed jlp765 closed 1 year ago

jlp765 commented 1 year ago

mawk -Wdump 'BEGIN{;}'

or any -W option causes a segmentation fault to randomly occur even when compiled with -O0 to turn optimisations off.

Tested on mawk snapshot label t20230322 on a Linux 5.15.90.1-microsoft-standard-WSL2 SMP x86_64 x86_64 x86_64 GNU/Linux

Line 598 of init.c for (j = 0; j < (int) strlen(optArg); j = (int) (optNext - optArg)) { doesn't handle optNext being null when there is no next optNext, and j is therefore a large negative number and line 599 char *name = optArg + j; segfaults randomly.

This fixed it for me: for (j = 0; j >= 0 && j < (int) strlen(optArg); j = (int) (optNext - optArg)) {

ThomasDickey commented 1 year ago

maybe (will investigate) - I get this:

$ mawk -Wdump 'BEGIN{;}'
BEGIN
000 .   exit0
jlp765 commented 1 year ago

Its random. Run it multiple times.
It may also be a quirk of the OS I run on (ubuntu in WSL on windows 10).

However it very reproducable for me.

Also, enabling debugging and using gdb did not produce it, so fault finding is by printf statements.

ThomasDickey commented 1 year ago

I see - if I use Address Sanitizer, it'll fail "frequently". Otherwise, too rarely to notice.

ThomasDickey commented 1 year ago

I mistrust the sign-check on a cast, so I did this:

diff -u -r1.74 init.c
--- init.c  2021/05/29 00:00:53 1.74 
+++ init.c  2023/04/03 22:54:11 
@@ -1,6 +1,6 @@ 
 /********************************************
 init.c
-copyright 2008-2020,2021, Thomas E. Dickey 
+copyright 2008-2021,2023, Thomas E. Dickey 
 copyright 1991-1994,1995, Michael D. Brennan

 This is a source file for mawk, an implementation of
@@ -11,7 +11,7 @@ 
 ********************************************/

 /*
- * $MawkId: init.c,v 1.74 2021/05/29 00:00:53 tom Exp $ 
+ * $MawkId: init.c,v 1.75 2023/04/03 22:54:11 tom Exp $ 
  */

 /* init.c */
@@ -595,7 +595,11 @@ 
    switch (curArg[1]) {

    case 'W':
-       for (j = 0; j < (int) strlen(optArg); j = (int) (optNext - optArg)) {   
+       for (j = 0; 
+        j < (int) strlen(optArg); 
+        j = (optNext 
+             ? (int) (optNext - optArg) 
+             : (int) strlen(optArg))) { 
        char *name = optArg + j;
        int args = 0;
        W_OPTIONS code = parse_w_opt(name, &optNext, &args);