PJK/libcbor

oss-fuzz driver broken for dataflow

PJK opened this issue · 6 comments

PJK commented

@James-ZHANG, it looks like adding C++ stdlib to the fuzzer loader has broken the linkage for oss-fuzz dataflow analyzer: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=21411

I have attempted to work around this in https://github.com/PJK/libcbor/tree/pk/ossfuzz by putting the c++ bits into a separate compilation unit, but that didn't seem to work.

Do you have any idea how to fix this?

Hi, Pavel,

The log suggests that the build of libcbor works but the installation of .pc file fails. My guess is that cmake install does some additional checking after copying the .pc file (maybe a test compile?) and that additional checking fails, due to some weird effect of -fsanitize=dataflow.

Perhaps the easiest fix is to disable pc file installing whenever -fsanitize=dataflow is in CXX_FLAGS? That would be a workaround if the problem is solely a cmake install problem.

PJK commented

The error (excerpt below) comes from linking part of the build.sh file build command. Note the object files it is referring to:

Step #69: /tmp/cbor_load_fuzzer-544ae7.o: In function `dfs$__clang_call_terminate':
Step #69: cbor_load_fuzzer.cc:(.text.dfs$__clang_call_terminate[__clang_call_terminate]+0x2): undefined reference to `dfs$__cxa_begin_catch'
Step #69: cbor_load_fuzzer.cc:(.text.dfs$__clang_call_terminate[__clang_call_terminate]+0x7): undefined reference to `dfs$_ZSt9terminatev'
Step #69: /tmp/cbor_load_fuzzer-544ae7.o: In function `dfs$_ZNSt3__117_DeallocateCaller9__do_callEPv':
Step #69: /usr/local/bin/../include/c++/v1/new:334: undefined reference to `dfs$_ZdlPv'
Step #69: /tmp/cbor_load_fuzzer-544ae7.o: In function `dfs$_ZNSt3__112__hash_tableINS_17__hash_value_typeIPvmEENS_22__unordered_map_hasherIS2_S3_NS_4hashIS2_EELb1EEENS_21__unordered_map_equalIS2_S3_NS_8equal_toIS2_EELb1EEENS_9allocatorIS3_EEE6rehashEm':
Step #69: /usr/local/bin/../include/c++/v1/__hash_table:2379: undefined reference to `dfs$_ZNSt3__112__next_primeEm'
Step #69: /usr/local/bin/../include/c++/v1/__hash_table:2389: undefined reference to `dfs$_ZNSt3__112__next_primeEm'
Step #69: /tmp/cbor_load_fuzzer-544ae7.o: In function `dfs$_ZNSt3__120__throw_length_errorEPKc':
Step #69: /usr/local/bin/../include/c++/v1/stdexcept:251: undefined reference to `dfs$__cxa_allocate_exception'
Step #69: /usr/local/bin/../include/c++/v1/stdexcept:251: undefined reference to `dfs$_ZNSt12length_errorD1Ev'
Step #69: /usr/local/bin/../include/c++/v1/stdexcept:251: undefined reference to `dfs$__cxa_throw'
Step #69: /usr/local/bin/../include/c++/v1/stdexcept:251: undefined reference to `dfs$__cxa_free_exception'
Step #69: /tmp/cbor_load_fuzzer-544ae7.o: In function `dfs$_ZNSt3__117__libcpp_allocateEmm':
Step #69: /usr/local/bin/../include/c++/v1/new:253: undefined reference to `dfs$_Znwm'
Step #69: /tmp/cbor_load_fuzzer-544ae7.o: In function `dfs$_ZNSt12length_errorC2EPKc':
Step #69: /usr/local/bin/../include/c++/v1/stdexcept:153: undefined reference to `dfs$_ZNSt11logic_errorC2EPKc'
Step #69: /tmp/cbor_load_fuzzer-544ae7.o:(.data.DW.ref.dfs$__gxx_personality_v0[DW.ref.dfs$__gxx_personality_v0]+0x0): undefined reference to `dfs$__gxx_personality_v0'

OK. I found an old thread about llvm's dfsan here. Not sure whether it's relevant, but it looks like one has to re-compile the whole libc++ for the linkage to work.

IMHO this is a bug of oss-fuzz: the base image should guarantee no such linkage error occurs. For a quick work around, we can, of course, use a pure-C implementation of hash maps. If you agree, I can work along your branch implementing that.

PJK commented

Good find, that looks like a likely explanation. So the options are 1/ make malloc unlimited again, 2/ rewrite the thing in C, or 3/ disable the dataflow analysis.

Before you invest a lot of effort into option 2, does it make sense to try if 1 would work given we also have the stack limit now?

I think 1 is the best. Indeed, the original stack-overflow problem was not related to heap size limit, but due to unbound context stack size. A big malloc or insufficient heap would simply return NULL, failing the decoding gracefully.