Project: libsass (sass/libsass), language: c++
Vulnerability instance: libsass.cve-2018-19839
Sanitizer: address

================= Bug Report (1/1) ==================
## Source: GitHub Issue
## URL: https://github.com/sass/libsass/issues/2657
## Description:
Issue: sass/libsass#2657
Title: AddressSanitizer: buffer-overflow (OOB read) against some invalid input (sass_context.cpp:81)
State: closed
Created by: hongxuchen
Created at: 2018-06-02 07:01:37+00:00
Labels: Fuzzy

Issue Body:
We found with our fuzzer some buffer over flow errors during `handle_error` (45f50873962b7d1c66bd115ba6e644bdaaf6cac1) against some invalid inputs when compiled with Address Sanitizer.
```
=================================================================
==17354==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000ef93 at pc 0x7fd92efcd656 bp 0x7fff0a43b4f0 sp 0x7fff0a43b4e0
READ of size 1 at 0x60200000ef93 thread T0
    #0 0x7fd92efcd655 in handle_error /home/xiaofei/FUZZ/libsass-orig/src/sass_context.cpp:81
    #1 0x7fd92efceb9f in handle_errors /home/xiaofei/FUZZ/libsass-orig/src/sass_context.cpp:207
    #2 0x7fd92f35ad8d in sass_parse_block /home/xiaofei/FUZZ/libsass-orig/src/sass_context.cpp:253
    #3 0x7fd92f35ad8d in sass_compiler_parse /home/xiaofei/FUZZ/libsass-orig/src/sass_context.cpp:483
    #4 0x7fd92f35aec8 in sass_compile_context /home/xiaofei/FUZZ/libsass-orig/src/sass_context.cpp:371
    #5 0x402d35 in compile_file /home/xiaofei/FUZZ/sassc-orig/sassc.c:158
    #6 0x402456 in main /home/xiaofei/FUZZ/sassc-orig/sassc.c:375
    #7 0x7fd92eb2a82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
    #8 0x402748 in _start (/home/xiaofei/FUZZ/sassc-orig/install/bin/sassc+0x402748)

0x60200000ef93 is located 0 bytes to the right of 3-byte region [0x60200000ef90,0x60200000ef93)
allocated by thread T0 here:
    #0 0x7fd92f6f5602 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602)
    #1 0x7fd92f133403 in Sass::File::read_file(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /home/xiaofei/FUZZ/libsass-orig/src/file.cpp:463

SUMMARY: AddressSanitizer: heap-buffer-overflow /home/xiaofei/FUZZ/libsass-orig/src/sass_context.cpp:81 handle_error
Shadow bytes around the buggy address:
  0x0c047fff9da0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9db0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9dc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fd fd
  0x0c047fff9dd0: fa fa fd fa fa fa 00 fa fa fa 00 00 fa fa 00 06
  0x0c047fff9de0: fa fa 00 00 fa fa 00 fa fa fa fd fa fa fa 00 06
=>0x0c047fff9df0: fa fa[03]fa fa fa 00 06 fa fa fd fd fa fa 00 00
  0x0c047fff9e00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9e10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9e20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9e30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9e40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
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
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  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
==17354==ABORTING
```

sample input files:
[test_m001.txt](https://github.com/sass/libsass/files/2064758/test_m001.txt)
[test_m002.txt](https://github.com/sass/libsass/files/2064759/test_m002.txt)
[test_m003.txt](https://github.com/sass/libsass/files/2064760/test_m003.txt)



Comments:
Comment by hongxuchen on 2018-06-03 02:35:08+00:00:
Another heap buffer overflow happens nearby:

```
=================================================================
==6731==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000efdd at pc 0x7fcdb81f7565 bp 0x7ffd03f0a200 sp 0x7ffd03f0a1f0
READ of size 1 at 0x60200000efdd thread T0
    #0 0x7fcdb81f7564 in unsigned int utf8::unchecked::next<char const*>(char const*&) utf8/unchecked.h:84
    #1 0x7fcdb7e6966e in handle_error /home/xiaofei/FUZZ/libsass-orig/src/sass_context.cpp :84
    #2 0x7fcdb7e6ab9f in handle_errors /home/xiaofei/FUZZ/libsass-orig/src/sass_context.cpp:207
    #3 0x7fcdb81f6d8d in sass_parse_block /home/xiaofei/FUZZ/libsass-orig/src/sass_context.cpp:253
    #4 0x7fcdb81f6d8d in sass_compiler_parse /home/xiaofei/FUZZ/libsass-orig/src/sass_context.cpp:483
    #5 0x7fcdb81f6ec8 in sass_compile_context /home/xiaofei/FUZZ/libsass-orig/src/sass_context.cpp:371
    #6 0x402d35 in compile_file /home/xiaofei/FUZZ/sassc-orig/sassc.c:158
    #7 0x402456 in main /home/xiaofei/FUZZ/sassc-orig/sassc.c:375
    #8 0x7fcdb79c682f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
    #9 0x402748 in _start (/home/xiaofei/FUZZ/sassc-orig/install/bin/sassc+0x402748)

0x60200000efdd is located 0 bytes to the right of 13-byte region [0x60200000efd0,0x60200000efdd)
allocated by thread T0 here:
    #0 0x7fcdb8591602 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602)
    #1 0x7fcdb7fcf403 in Sass::File::read_file(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /home/xiaofei/FUZZ/libsass-orig/src/file.cpp:463

SUMMARY: AddressSanitizer: heap-buffer-overflow utf8/unchecked.h:84 unsigned int utf8::unchecked::next<char const*>(char const*&)
Shadow bytes around the buggy address:
  0x0c047fff9da0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9db0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9dc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9dd0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fd fd
  0x0c047fff9de0: fa fa fd fa fa fa 00 fa fa fa 00 00 fa fa 00 00
=>0x0c047fff9df0: fa fa 00 fa fa fa fd fa fa fa 00[05]fa fa 00 00
  0x0c047fff9e00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9e10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9e20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9e30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9e40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
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
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  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
==6731==ABORTING
```

sample inputs:
[test_m004.txt](https://github.com/sass/libsass/files/2065579/test_m004.txt)
[test_m005.txt](https://github.com/sass/libsass/files/2065580/test_m005.txt)

---

Comment by glebm on 2018-11-27 23:40:56+00:00:
I believe this is a bug in utf8cpp.

I've opened an issue (https://github.com/ledger/utfcpp/issues/2) and sent a fix (https://github.com/ledger/utfcpp/pull/3).

---

Comment by glebm on 2018-11-28 00:12:33+00:00:
Nevermind, was looking at the wrong utfcpp mirror. The right one is probably https://github.com/nemtrif/utfcpp. Checking to see if the bug is already fixed there.

Attachments:
https://github.com/sass/libsass/files/2064758/test_m001.txt
https://github.com/sass/libsass/files/2064760/test_m003.txt
https://github.com/sass/libsass/files/2065580/test_m005.txt
https://github.com/sass/libsass/files/2064759/test_m002.txt
https://github.com/sass/libsass/files/2065579/test_m004.txt

Commit References:
45f50873962b7d1c66bd115ba6e644bdaaf6cac1

Build script:
#!/bin/bash -eu
# Minimized build script with only core build commands
set -eu
export BUILD='static'
make -j$(nproc)

Dockerfile:
FROM hwiwonlee/secb.base:latest
RUN apt-get update && apt-get install -y make autoconf automake libtool
RUN git clone https://github.com/sass/libsass libsass
RUN git -C libsass checkout 9ce7a7fd913b70dab2107edb2e50aff7bacc56af
WORKDIR $SRC/libsass
COPY build.sh $SRC/

Additional files:
filename: data_context_fuzzer.cc
content: #include "sass.h"

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
  char* sass_data = (char*) malloc(sizeof(char) * size + 1);
  if (sass_data == NULL) return 0;

  memcpy(sass_data, data, size);
  sass_data[size] = '\0';

  struct Sass_Data_Context* ctx = sass_make_data_context(sass_data);
  if (ctx == NULL) {
    free(sass_data);
    return 0;
  }

  struct Sass_Options* options = sass_make_options();
  if (options == NULL) {
    sass_delete_data_context(ctx);
    return 0;
  }

  sass_option_set_output_style(options, SASS_STYLE_NESTED);
  sass_option_set_precision(options, 5);

  sass_data_context_set_options(ctx, options);
  sass_compile_data_context(ctx);

  sass_delete_data_context(ctx);
  sass_delete_options(options);

  return 0;
}