这是indexloc提供的服务,不要输入任何密码
Self-registration is disabled due to spam issue (mail gorcunov@gmail.com or hpa@zytor.com to create an account)
Bug 3392761 - NULL Pointer dereference on do_directive caused by %unmacro
Summary: NULL Pointer dereference on do_directive caused by %unmacro
Status: OPEN
Alias: None
Product: NASM
Classification: Unclassified
Component: Assembler (show other bugs)
Version: 2.16.xx
Hardware: PC Linux
: Medium normal
Assignee: nobody
URL:
Depends on:
Blocks:
 
Reported: 2021-06-02 13:40 PDT by Marco
Modified: 2021-06-02 13:41 PDT (History)
5 users (show)

Obtained from: Built from git using configure
Generated by: ---
Bug category:
Breaks existing code: ---


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Marco 2021-06-02 13:40:34 PDT
There's a NULL pointer dereference in the do_directive function, caused by an %unmacro.

Here's a reproducer:

```asm
%macro baz 0
  %unmacro F 0
%endmacro
baz
```

Compile it with:

```shell
$ nasm -f elf64 -g -F DWARF -o tmp.o -werror file.asm
```

Compile nasm with address sanitizer support.

Here's the Address Sanitizer error:

```
asm/preproc.c:4336:32: runtime error: load of null pointer of type 'MMacro *' (aka 'struct MMacro *')
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior asm/preproc.c:4336:32 in 
AddressSanitizer:DEADLYSIGNAL
=================================================================
==766206==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x00000056ee95 bp 0x7ffe64c14990 sp 0x7ffe64c14480 T0)
==766206==The signal is caused by a READ memory access.
==766206==Hint: address points to the zero page.
    #0 0x56ee95 in do_directive /home/markov/nasm/asm/preproc.c:4336:29
    #1 0x5331f9 in pp_tokline /home/markov/nasm/asm/preproc.c:7264:13
    #2 0x530674 in pp_getline /home/markov/nasm/asm/preproc.c:7328:17
    #3 0x4bf742 in assemble_file /home/markov/nasm/asm/nasm.c:1722:24
    #4 0x4bf742 in main /home/markov/nasm/asm/nasm.c:717:9
    #5 0x7f0cb2a4a0b2 in __libc_start_main /build/glibc-eX1tMB/glibc-2.31/csu/../csu/libc-start.c:308:16
    #6 0x41c64d in _start (/home/markov/nasm/nasm+0x41c64d)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /home/markov/nasm/asm/preproc.c:4336:29 in do_directive
==766206==ABORTING

```

In the case of PP_UNMACRO, it will populate `mmac_p` with `(MMacro **) hash_findi(&mmacros, spec.name, NULL);`, but that might return NULL.

Thus, in the following lines, there's this code:

```
        /* Check the macro to be undefined is not being expanded */
        list_for_each(l, istk->expansion) {
            if (l->finishes == *mmac_p) {
                nasm_nonfatal("`%%unmacro' can't undefine the macro being expanded");
                /*
                 * Do not release the macro instance to avoid using the freed
                 * memory while proceeding the expansion.
                 */
                goto done;
            }
        }
```

Dereferencing mmac_p inside that list_for_each is invalid if mmac_p is NULL.
Comment 1 Marco 2021-06-02 13:41:39 PDT
This could be fixed by wrapping the list with an `if (mmac_p != NULL)`, but I am not sure there's something down the line that should also be fixed