-
Notifications
You must be signed in to change notification settings - Fork 376
Description
Hi,
we have found a null pointer dereference and would like to report this issue.
Summary
A null pointer dereference occurs when -w*<option> is passed as a command-line argument, where <option> is any string listed in [Appendix A: List of Warning Classes](https://www.nasm.us/xdoc/2.16.03/html/nasmdoca.html).
Examples include -w*all or -w*db-empty.
Details
- Vulnerability Type: Null pointer dereference
Reproduction
Tested Environment
- Operating System: Ubuntu 24.04 LTS
- Architecture: x86_64
- Compiler: gcc with AddressSanitizer (gcc version: 13.3.0)
Reproduction Steps
# Setup
git clone https://github.com/netwide-assembler/nasm.git
cd nasm
git reset --hard 9ea92eab6e26b5527e2dc72424a886a1a4061a48
# Compile
sh configure --enable-debug --enable-sanitizer
make -j$(nproc)
# Execute
./nasm -w*allOutput
asm/error.c:277:62: runtime error: member access within null pointer of type 'struct warning_stack'
AddressSanitizer:DEADLYSIGNAL
=================================================================
==10875==ERROR: AddressSanitizer: SEGV on unknown address 0x00000000002b (pc 0x60fe87c5e46f bp 0x7fff4d47cf00 sp 0x7fff4d47cec0 T0)
==10875==The signal is caused by a READ memory access.
==10875==Hint: address points to the zero page.
#0 0x60fe87c5e46f in set_warning_status asm/error.c:277
#1 0x60fe87c511ee in process_arg asm/nasm.c:1175
#2 0x60fe87c53d3e in parse_cmdline asm/nasm.c:1528
#3 0x60fe87c4dd5a in main asm/nasm.c:577
#4 0x7181c37961c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
#5 0x7181c379628a in __libc_start_main_impl ../csu/libc-start.c:360
#6 0x60fe87c49e84 in _start (/tmp/nasm/nasm+0x2f1e84) (BuildId: 7bbd4136811f1c64a3445055037bf9ee7294a5ab)
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV asm/error.c:277 in set_warning_status
==10875==ABORTING
Root Cause Analysis
The null pointer dereference occurs at the following location in the set_warning_status() function, where the static variable warning_state_init is null:
Line 277 in 9ea92ea
| warning_state[i] |= warning_state_init->state[i] & mask; |
case WID_RESET:
warning_state[i] &= ~mask;
warning_state[i] |= warning_state_init->state[i] & mask;
break;
}This code path is executed when -w*<option> is specified as a command-line argument. The caller is the following function invoked in main():
Line 577 in 9ea92ea
| parse_cmdline(argc, argv, 2); |
parse_cmdline(argc, argv, 2);However, warning_state_init is initialized later, in the following function called after the above invocation:
Line 585 in 9ea92ea
| init_warnings(); |
init_warnings();Line 148 in 9ea92ea
| void init_warnings(void) |
void init_warnings(void)
{
push_warnings();
warning_state_init = warning_stack;
}In other words, the root cause is that warning_state_init is being used before it is initialized.
Proposed Fix
When [-w](https://www.nasm.us/xdoc/2.16.03/html/nasmdoc2.html#section-2.1.26)*<option> is passed as a command-line argument, the first character of the string value passed to the bool set_warning_status(const char *value) function becomes *. However, the case where the first character of value is * should only be expected when used from the [WARNING] directive, not from the command-line argument -w. Therefore, when -w* is specified as a command-line argument, the program should exit.
diff --git a/asm/nasm.c b/asm/nasm.c
index 851f7cc..689a339 100644
--- a/asm/nasm.c
+++ b/asm/nasm.c
@@ -1171,8 +1171,13 @@ static bool process_arg(char *p, char *q, int pass)
case 'w':
case 'W':
- if (pass == 2)
+ if (pass == 2) {
+ if (p[2] == '*') {
+ help(stdout, "-w");
+ exit(0);
+ }
set_warning_status(param);
+ }
break;
case 'M':Note: This issue appears to have been previously reported and remains open: