CVE-2020-24240 (Other, published 2020-08-25T14:15Z)
Description: value: GNU Bison before 3.7.1 has a use-after-free in _obstack_free in lib/obstack.c (called from gram_lex) when a '\0' byte is encountered. NOTE: there is a risk only if Bison is used with untrusted input, and the observed bug happens to cause unsafe behavior with a specific compiler/architecture. The bug report was intended to show that a crash may occur in Bison itself, not that a crash may occur in code that is generated by Bison.
Severity: HIGH (CVSS v3 base score: 5.5)
Weakness: CWE-416 \u2014 Use After Free
The product reuses or references memory after it has been freed. At some point afterward, the memory may be allocated again and saved in another pointer, while the original pointer references a location somewhere within the new allocation. Any operations using the original pointer are no longer valid because the memory "belongs" to the code that operates on the new pointer.
Repository: https://github.com/akimd/bison
Files changed:
THANKS
src/flex-scanner.h
src/scan-gram.l
tests/input.at
Commit message: scanner: don't crash on strings containing a NUL byte

We crash if the input contains a string containing a NUL byte.
Reported by Suhwan Song.
https://lists.gnu.org/r/bug-bison/2020-07/msg00051.html

* src/flex-scanner.h (STRING_FREE): Avoid accidental use of
last_string.
* src/scan-gram.l: Don't call STRING_FREE without calling
STRING_FINISH first.
* tests/input.at (Invalid inputs): Check that case.


Vulnerable code:
# define STRING_FREE()                                  \
    val->CHAR = last_string[0];
# Checking the Bison scanner.                    -*- Autotest -*-
AT_BISON_CHECK([input.y], [1], [],
input.y:3.1: error: invalid character: '?'
input.y:4.14: error: invalid character: '}'
input.y:5.1: error: invalid character: '%'
input.y:5.2: error: invalid character: '&'
input.y:6.1-17: error: invalid directive: '%a-does-not-exist'
input.y:7.1: error: invalid character: '%'
input.y:7.2: error: invalid character: '-'
input.y:8.1-9.0: error: missing '%}' at end of file

Fixed code:
Suhwan Song               prada960808@gmail.com
# ifdef NDEBUG
#  define STRING_FREE()                                 \
# else
#  define STRING_FREE()                                  \
  do {                                                   \
    obstack_free (&obstack_for_string, last_string);     \
    last_string = NULL;                                  \
  } while (0)
#endif
    STRING_FINISH ();
        val->CHAR = last_string[0];
# Checking the Bison reader.                    -*- Autotest -*-
# The truly bad guys no human would write, but easily uncovered by
# fuzzers.
"\000"
AT_BISON_CHECK([-fcaret input.y], [1], [], [stderr])

# Autotest's diffing, when there are NUL bytes, just reports "binary
# files differ".  So don't leave NUL bytes.
AT_PERL_CHECK([[-p -e 's{([\0\377])}{sprintf "\\x%02x", ord($1)}ge' stderr]], [],
    1 | \x00\xff?
      | ^~
input.y:2.2: error: invalid null character
    2 | "\x00"
      |  ^
input.y:4.1: error: invalid character: '?'
    4 | ?
      | ^
input.y:5.14: error: invalid character: '}'
    5 | default: 'a' }
      |              ^
input.y:6.1: error: invalid character: '%'
    6 | %&
      | ^
input.y:6.2: error: invalid character: '&'
    6 | %&
      |  ^
input.y:7.1-17: error: invalid directive: '%a-does-not-exist'
    7 | %a-does-not-exist
      | ^~~~~~~~~~~~~~~~~
input.y:8.1: error: invalid character: '%'
    8 | %-
      | ^
input.y:8.2: error: invalid character: '-'
    8 | %-
      |  ^
input.y:9.1-10.0: error: missing '%}' at end of file
    9 | %{
      | ^~