Skip to content

NULL Pointer Dereference in expr_func() when funcs is NULL (CWE-476) - Discovered via AFL Fuzzing #8

@3291710458

Description

@3291710458

Vulnerability Summary

Field Detail
Vulnerability NULL Pointer Dereference (CWE-476)
Severity Medium (CVSS 5.5)
Location expr.h:247 in expr_func()
Discovery Method AFL fuzzing — deterministic bit-flip phase

Technical Description

A NULL pointer dereference exists in expr_func() at line 247 of expr.h. The function accepts a funcs parameter but never checks if funcs is NULL before dereferencing f->name:

static struct expr_func *expr_func(struct expr_func *funcs, const char *s,
                                   size_t len) {
  for (struct expr_func *f = funcs; f->name; f++) {  // LINE 247: NULL deref
    if (strlen(f->name) == len && strncmp(f->name, s, len) == 0) {
      return f;
    }
  }
  return NULL;
}

When expr_create() is called with funcs = NULL and the expression contains an identifier followed by parentheses (e.g., foo(...)), the parser calls expr_func(NULL, ...) which crashes with a segmentation fault.

Call chain:

  1. expr_create(buf, len, &vars, NULL) — parse with no registered functions
  2. Parser encounters <identifier>( pattern
  3. expr_func(NULL, "identifier", len) at line 658
  4. f = NULL; f->name at line 247 → SEGV

AFL Discovery (Not Manual Audit)

This vulnerability was discovered exclusively through AFL fuzzing, not through source code review.

  • AFL Crash ID: id:000010,sig:11,src:000001,op:flip1,pos:11
  • Mutation: AFL's deterministic bit-flip phase flipped bit 3 of position 11 (space 0x20( 0x28)
  • Original seed: x = 5 + 3\ny = x * 2 (valid expression)
  • Mutated input: x = 5 + 3\ny(= x * 2 (created y( function-call syntax)
  • ASAN backtrace:
==1276173==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000
    #0 expr_func /home/ubuntu/fuzzing/zserge-expr/expr.h:247
    #1 expr_create /home/ubuntu/fuzzing/zserge-expr/expr.h:658
    #2 main /home/ubuntu/fuzzing/zserge-expr/harness.c:39

AFL found 19 unique crash variants through deterministic and havoc phases.

Impact

Any application using expr to parse user-supplied expressions without registering function handlers is vulnerable to a denial-of-service attack. A malicious user can submit any identifier followed by parentheses (e.g., foo(1), x()) to crash the application.

Fix

Add a NULL check at the beginning of expr_func():

static struct expr_func *expr_func(struct expr_func *funcs, const char *s,
                                   size_t len) {
  if (funcs == NULL) return NULL;  // ADD THIS CHECK
  for (struct expr_func *f = funcs; f->name; f++) {
    if (strlen(f->name) == len && strncmp(f->name, s, len) == 0) {
      return f;
    }
  }
  return NULL;
}

Reproduction

gcc -fsanitize=address -g -O1 -o harness_asan harness.c -lm
echo 'x()' | ./harness_asan  # SIGSEGV

中文摘要

漏洞概述

expr.h 第 247 行 expr_func() 中存在空指针解引用漏洞。该函数接受 funcs 参数但从未检查是否为 NULL。当 expr_create()funcs = NULL 调用且表达式包含 foo(...) 模式时,程序崩溃。

AFL 发现

此漏洞完全通过 AFL 模糊测试发现,而非源代码审查。AFL 确定性位翻转阶段将输入中的空格字符变为 (,创建了函数调用语法并触发了空指针解引用。

ASAN 回溯: 空指针解引用位于 expr.h:247: for (struct expr_func *f = funcs; f->name; f++)

修复方案

expr_func() 开头添加 if (funcs == NULL) return NULL;

CVSS 评分

CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H (5.5 中等)


Discovery Metadata

Field Value
Fuzzer AFL 2.57b
Total execs before crash ~27,000
Discovery phase Deterministic bit-flip (flip1)
Crashes found 19 unique
ASAN verified Yes

🤖 Generated with Claude Code

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