YosysHQ / yosys

Yosys Open SYnthesis Suite
https://yosyshq.net/yosys/
ISC License
3.5k stars 895 forks source link

Port names starting with '%' cause stack buffer overflow during error reporting #4599

Open mattyoung101 opened 2 months ago

mattyoung101 commented 2 months ago

Version

Yosys 0.45+106 (git sha1 c1228fec2, clang++ 18.1.8 -Og -fPIC -O1 -fno-omit-frame-pointer -fno-optimize-sibling-calls -fsanitize=address)

On which OS did this happen?

Linux

Reproduction Steps

The following script, issue.ys, will cause a stack buffer overflow and crash when run under AddressSanitizer:

read_verilog <<EOT
module sc1 (i1 ,
            %i11,
);

endmodule
EOT

(run with yosys -s issue.ys).

This was found via fuzzing using Honggfuzz as a quick experiment from me (see my setup here: https://github.com/mattyoung101/yosys_honggfuzz_docker, script is a bit ugly sorry) and I manually minimised the issue down to the '%' character in the port name.

I'll also just ping issue #613 since that seems to track fuzzing Yosys, although I'm using Honggfuzz not AFL++.

Expected Behavior

Yosys does not stack buffer overflow when presented with this input.

Actual Behavior

Yosys stack buffer overflows, presumably due to malformed format string. Here is the output of AddressSanitizer:

$ ./workspace/yosys/yosys -s issue.ys

 /----------------------------------------------------------------------------\
 |  yosys -- Yosys Open SYnthesis Suite                                       |
 |  Copyright (C) 2012 - 2024  Claire Xenia Wolf <claire@yosyshq.com>         |
 |  Distributed under an ISC-like license, type "license" to see terms        |
 \----------------------------------------------------------------------------/
 Yosys 0.45+106 (git sha1 c1228fec2, clang++ 18.1.8 -Og -fPIC -O1 -fno-omit-frame-pointer -fno-optimize-sibling-calls -fsanitize=address)

-- Executing script file `issue.ys' --

1. Executing Verilog-2005 frontend: <<EOT
Parsing Verilog input from `<<EOT' to AST representation.
==288487==AddressSanitizer: WARNING: unexpected format specifier in printf interceptor: %' (reported once per process)
=================================================================
==288487==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x74aec171605f at pc 0x6201adcc0acc bp 0x7fffa6083700 sp 0x7fffa6082ec0
WRITE of size 2 at 0x74aec171605f thread T0
    #0 0x6201adcc0acb in vsnprintf (/home/matt/workspace/yosys/yosys+0x61aacb) (BuildId: 8f208afdbc76256e985b6415460625947550bc3d)
    #1 0x6201adcc2e6d in snprintf (/home/matt/workspace/yosys/yosys+0x61ce6d) (BuildId: 8f208afdbc76256e985b6415460625947550bc3d)
    #2 0x6201ae502bea in frontend_verilog_yyerror(char const*, ...) /home/matt/workspace/yosys/frontends/verilog/verilog_frontend.cc:686:7
    #3 0x6201ae4a11e6 in frontend_verilog_yyparse() /home/matt/workspace/yosys/frontends/verilog/verilog_parser.tab.cc:8557:9
    #4 0x6201ae50749b in Yosys::VerilogFrontend::execute(std::istream*&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>>, Yosys::RTLIL::Design*) /home/matt/workspace/yosys/frontends/verilog/verilog_frontend.cc:512:3
    #5 0x6201add88a82 in Yosys::Frontend::execute(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>>, Yosys::RTLIL::Design*) /home/matt/workspace/yosys/kernel/register.cc:469:3
    #6 0x6201add843f6 in Yosys::Pass::call(Yosys::RTLIL::Design*, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>>) /home/matt/workspace/yosys/kernel/register.cc:317:26
    #7 0x6201add8348c in Yosys::Pass::call(Yosys::RTLIL::Design*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>) /home/matt/workspace/yosys/kernel/register.cc:294:2
    #8 0x6201adf3cdf6 in Yosys::run_frontend(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, Yosys::RTLIL::Design*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*) /home/matt/workspace/yosys/kernel/yosys.cc:1209:6
    #9 0x6201add412c0 in main /home/matt/workspace/yosys/kernel/driver.cc:642:4
    #10 0x74aec3394e07 in __libc_start_call_main /usr/src/debug/glibc/glibc/csu/../sysdeps/nptl/libc_start_call_main.h:58:16
    #11 0x74aec3394ecb in __libc_start_main /usr/src/debug/glibc/glibc/csu/../csu/libc-start.c:360:3
    #12 0x6201adc04df4 in _start (/home/matt/workspace/yosys/yosys+0x55edf4) (BuildId: 8f208afdbc76256e985b6415460625947550bc3d)

Address 0x74aec171605f is located in stack of thread T0 at offset 95 in frame
    #0 0x6201ae502a4f in frontend_verilog_yyerror(char const*, ...) /home/matt/workspace/yosys/frontends/verilog/verilog_frontend.cc:679

  This frame has 2 object(s):
    [32, 56) 'ap' (line 680)
    [96, 1120) 'buffer' (line 681) <== Memory access at offset 95 partially underflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow (/home/matt/workspace/yosys/yosys+0x61aacb) (BuildId: 8f208afdbc76256e985b6415460625947550bc3d) in vsnprintf
Shadow bytes around the buggy address:
  0x74aec1715d80: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
  0x74aec1715e00: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
  0x74aec1715e80: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
  0x74aec1715f00: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
  0x74aec1715f80: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
=>0x74aec1716000: f1 f1 f1 f1 00 00 00 f2 f2 f2 f2[f2]00 00 00 00
  0x74aec1716080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x74aec1716100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x74aec1716180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x74aec1716200: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x74aec1716280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==288487==ABORTING
mattyoung101 commented 2 months ago

Also - let me know if these fuzzer issues are just noise and you'd prefer not to see them, as I don't want to be a nuisance (I know people with fuzzers can be like that sometimes). Cheers :)

whitequark commented 2 months ago

This is a great example of a useful and responsibly reported issue discovered by fuzzing, actually!