Skip to content

Null Pointer Dereference via -w*<option> Command-Line Argument #155

Description

@momo-trip

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*all

Output

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:

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():

nasm/asm/nasm.c

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:

nasm/asm/nasm.c

Line 585 in 9ea92ea

init_warnings();

    init_warnings();

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:

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions