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

================= Bug Report (1/1) ==================
## Source: GitHub Issue
## URL: https://github.com/sass/libsass/issues/2663
## Description:
Issue: sass/libsass#2663
Title: AddressSanitizer: null pointer dereference (SEGV) in Sass::Functions::selector_append (libsass/src/functions.cpp:2088:13)
State: closed
Created by: glen-mac
Created at: 2018-06-03 02:24:31+00:00
Labels: Bug - Confirmed, Bug - Selectors, selector-validation, Fuzzy

Issue Body:
Hey there, I have discovered a null pointer dereference in libsass at: [functions.cpp:2088:13](https://github.com/sass/libsass/blob/60f839158eff1f1bb84cb44f0f0c4bce3ed86a6d/src/functions.cpp#L2088)

Found when fuzzing commit 60f839158eff1f1bb84cb44f0f0c4bce3ed86a6d of libsass, using commit [aa6d5c6](https://github.com/sass/sassc/commit/aa6d5c635ea8faf44d542a23aaf85d27e5777d48) of sassc as a harness.

Compile flags to reproduce: 
```
CC=clang CXX=clang++ CFLAGS='-fsanitize=address -g -O2 -fno-omit-frame-pointer' CXXFLAGS=$CFLAGS make -C sassc -j8
```

System information:
```
$ uname -a
Linux s127422 3.13.0-137-generic #186-Ubuntu SMP Mon Dec 4 19:09:19 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
```

This bug was found to be in libsass releases from [3.3.6](https://github.com/sass/libsass/tree/3.3.6) until the commit listed above.

You can find a collection of PoC files that trigger the bug [here](https://github.com/sass/libsass/files/2065572/functions_crashes.zip).

The full ASAN report is shown below:
```
↳ ./sassc.bin < crash.file
ASAN:DEADLYSIGNAL
=================================================================
==16225==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000098 (pc 0x0000005b8758 bp 0x7ffd5ab26780 sp 0x7ffd5ab25b80 T0)
    #0 0x5b8757 in Sass::Functions::selector_append(Sass::Environment<Sass::SharedImpl<Sass::AST_Node> >&, Sass::Environment<Sass::SharedImpl<Sass::AST_Node> >&, Sass::Context&, char const*, Sass::ParserState, Sass::Backtrace*, std::vector<Sass::SharedImpl<Sass::Selector_List>, std::allocator<Sass::SharedImpl<Sass::Selector_List> > >) /home/glenn/temp/libsass/src/functions.cpp:2088:13
    #1 0x6f6a04 in Sass::Eval::operator()(Sass::Function_Call*) /home/glenn/temp/libsass/src/eval.cpp:1030:18
    #2 0x6dbf8e in Sass::Eval::operator()(Sass::List*) /home/glenn/temp/libsass/src/eval.cpp:503:18
    #3 0x71cc5f in Sass::Expand::operator()(Sass::Assignment*) /home/glenn/temp/libsass/src/expand.cpp:330:29
    #4 0x731326 in Sass::Expand::append_block(Sass::Block*) /home/glenn/temp/libsass/src/expand.cpp:808:27
    #5 0x7269e4 in Sass::Expand::operator()(Sass::While*) /home/glenn/temp/libsass/src/expand.cpp:572:7
    #6 0x731326 in Sass::Expand::append_block(Sass::Block*) /home/glenn/temp/libsass/src/expand.cpp:808:27
    #7 0x714f0a in Sass::Expand::operator()(Sass::Block*) /home/glenn/temp/libsass/src/expand.cpp:81:5
    #8 0x5521f7 in Sass::Context::compile() /home/glenn/temp/libsass/src/context.cpp:659:12
    #9 0x55144c in Sass::Data_Context::parse() /home/glenn/temp/libsass/src/context.cpp:630:12
    #10 0x5200ca in Sass::sass_parse_block(Sass_Compiler*) /home/glenn/temp/libsass/src/sass_context.cpp:238:22
    #11 0x5200ca in sass_compiler_parse /home/glenn/temp/libsass/src/sass_context.cpp:487
    #12 0x51f6d9 in sass_compile_context(Sass_Context*, Sass::Context*) /home/glenn/temp/libsass/src/sass_context.cpp:375:7
    #13 0x51707d in compile_stdin /home/glenn/temp/findsass/sassc/sassc.c:138:5
    #14 0x517a8e in main /home/glenn/temp/findsass/sassc/sassc.c:375:18
    #15 0x7f7bf2feb82f in __libc_start_main /build/glibc-Cl5G7W/glibc-2.23/csu/../csu/libc-start.c:291
    #16 0x4456d8 in _start (/home/glenn/temp/findsass/sassc.bin+0x4456d8)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /home/glenn/temp/libsass/src/functions.cpp:2088:13 in Sass::Functions::selector_append(Sass::Environment<Sass::SharedImpl<Sass::AST_Node> >&, Sass::Environment<Sass::SharedImpl<Sass::AST_Node> >&, Sass::Context&, char const*, Sass::ParserState, Sass::Backtrace*, std::vector<Sass::SharedImpl<Sass::Selector_List>, std::allocator<Sass::SharedImpl<Sass::Selector_List> > >)
==16225==ABORTING
```


Comments:
Comment by xzyfer on 2018-07-04 11:06:21+00:00:
Thanks for the report. 
We confirmed this issue shares a common root cause to other reported issues.
We have assigned the `selector-validation` to the affected issues.

---

Comment by VictorRodriguez on 2018-07-19 14:04:06+00:00:
@xzyfer thanks a lot for the great support, do you have the patch of the common root cause issue? 

---

Comment by glebm on 2018-11-23 09:28:03+00:00:
There are two separate issues here:

First, the `&` parent selector shouldn't be allowed in `selector-append`. Example:

```scss
div {
  a: selector-append('.menu', 'li', '&');
}
```

I've sent a fix for this in #2760.

---

Second is this issue:

```scss
div {
  a: selector-append('.x~~', 'li', 'a')
}
```

dart-sass output:

```
Error: Parent ".x ~ ~" is incompatible with this selector.
  a: selector-append('.x~~', 'li', 'a')
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  ../../../tmp/test2.scss 2:6  root stylesheet
```

ruby-sass output:

```
Error: Invalid parent selector for "&li": ".x ~ ~"
        on line 2 of /home/glebm/tmp/test2.scss
  Use --trace for backtrace.
```

sassc output:

```
AddressSanitizer:DEADLYSIGNAL
=================================================================
==15981==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000088 (pc 0x0000005e7be1 bp 0x7ffd8aa90810 sp 0x7ffd8aa90740 T0)
==15981==The signal is caused by a READ memory access.
==15981==Hint: address points to the zero page.
    #0 0x5e7be0 in Sass::Vectorized<Sass::SharedImpl<Sass::Simple_Selector> >::concat(Sass::Vectorized<Sass::SharedImpl<Sass::Simple_Selector> >*) /home/glebm/repos/glebm/libsass/src/ast.hpp:288:61
    #1 0x5e3fc4 in Sass::Functions::selector_append(Sass::Environment<Sass::SharedImpl<Sass::AST_Node> >&, Sass::Environment<Sass::SharedImpl<Sass::AST_Node> >&, Sass::Context&, char const*, Sass::ParserState, std::vector<Sass::Backtrace, std::allocator<Sass::Backtrace> >&, std::vector<Sass::SharedImpl<Sass::Selector_List>, std::allocator<Sass::SharedImpl<Sass::Selector_List> > >&) /home/glebm/repos/glebm/libsass/src/fn_selectors.cpp:144:53
    #2 0x6a1c38 in Sass::Eval::operator()(Sass::Function_Call*) /home/glebm/repos/glebm/libsass/src/eval.cpp:1060:18
    #3 0x6c3274 in Sass::Expand::operator()(Sass::Declaration*) /home/glebm/repos/glebm/libsass/src/expand.cpp:250:31
    #4 0x6cea99 in Sass::Expand::append_block(Sass::Block*) /home/glebm/repos/glebm/libsass/src/expand.cpp:802:32
    #5 0x6bfbd9 in Sass::Expand::operator()(Sass::Block*) /home/glebm/repos/glebm/libsass/src/expand.cpp:72:11
    #6 0x6c0b9f in Sass::Expand::operator()(Sass::Ruleset*) /home/glebm/repos/glebm/libsass/src/expand.cpp:144:27
    #7 0x6cea99 in Sass::Expand::append_block(Sass::Block*) /home/glebm/repos/glebm/libsass/src/expand.cpp:802:32
    #8 0x6bfbd9 in Sass::Expand::operator()(Sass::Block*) /home/glebm/repos/glebm/libsass/src/expand.cpp:72:11
    #9 0x5768b6 in Sass::Context::compile() /home/glebm/repos/glebm/libsass/src/context.cpp:678:12
    #10 0x5758b7 in Sass::File_Context::parse() /home/glebm/repos/glebm/libsass/src/context.cpp:605:12
    #11 0x55bc76 in Sass::sass_parse_block(Sass_Compiler*) /home/glebm/repos/glebm/libsass/src/sass_context.cpp:234:31
    #12 0x55b8ba in sass_compiler_parse /home/glebm/repos/glebm/libsass/src/sass_context.cpp:483:22
    #13 0x55b539 in sass_compile_context(Sass_Context*, Sass::Context*) /home/glebm/repos/glebm/libsass/src/sass_context.cpp:371:7
    #14 0x5540f6 in compile_file /home/glebm/repos/glebm/libsass/sassc/sassc.c:158:5
    #15 0x554ab9 in main /home/glebm/repos/glebm/libsass/sassc/sassc.c:370:18
    #16 0x7ffbb3fcbb96 in __libc_start_main /build/glibc-OTsEL5/glibc-2.27/csu/../csu/libc-start.c:310
    #17 0x45b839 in _start (/home/glebm/repos/glebm/libsass/sassc/bin/sassc+0x45b839)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /home/glebm/repos/glebm/libsass/src/ast.hpp:288:61 in Sass::Vectorized<Sass::SharedImpl<Sass::Simple_Selector> >::concat(Sass::Vectorized<Sass::SharedImpl<Sass::Simple_Selector> >*)
==15981==ABORTING
```

I've sent https://github.com/sass/libsass/pull/2762 for this one but not sure if it's the best solution.

Attachments:
https://github.com/sass/libsass/files/2065572/functions_crashes.zip

Commit References:
60f839158eff1f1bb84cb44f0f0c4bce3ed86a6d
aa6d5c635ea8faf44d542a23aaf85d27e5777d48

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 1e52b74306b7d73a617396c912ca436dc55fd4d8
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;
}