Coverage Report

Created: 2026-08-13 06:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/c_api_fuzzer.cc
Line
Count
Source
1
/* Copyright 2026 Google LLC
2
3
Licensed under the Apache License, Version 2.0 (the "License");
4
you may not use this file except in compliance with the License.
5
You may obtain a copy of the License at
6
7
      http://www.apache.org/licenses/LICENSE-2.0
8
9
Unless required by applicable law or agreed to in writing, software
10
distributed under the License is distributed on an "AS IS" BASIS,
11
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
See the License for the specific language governing permissions and
13
limitations under the License.
14
*/
15
16
#include <stdint.h>
17
#include <stdio.h>
18
#include <string.h>
19
#include <vector>
20
#include <string>
21
22
#include "muParserDLL.h"
23
24
// Callbacks
25
220
muFloat_t MyFun1(muFloat_t v) { return v * 2; }
26
306
muFloat_t MyFun2(muFloat_t v1, muFloat_t v2) { return v1 + v2; }
27
290k
muFloat_t MyInfixFun(muFloat_t v) { return -v; }
28
5.12k
muFloat_t MyPostfixFun(muFloat_t v) { return v + 1; }
29
718
muFloat_t MyOprtFun(muFloat_t v1, muFloat_t v2) { return v1 * v2 + 1; }
30
31
28.1k
muFloat_t* MyVarFactory(const muChar_t* name, void* pUserData) {
32
28.1k
  static muFloat_t v[10];
33
28.1k
  return v;
34
28.1k
}
35
36
884k
muInt_t MyIdentFun(const muChar_t* name, muInt_t* pos, muFloat_t* val) {
37
884k
  if (strncmp(name, "test", 4) == 0) {
38
378
    *val = 123.0;
39
378
    *pos += 4;
40
378
    return 1;
41
378
  }
42
883k
  return 0;
43
884k
}
44
45
6.57k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
46
6.57k
  if (size < 10) return 0;
47
48
  // Use the first few bytes for configuration
49
6.56k
  uint8_t config = data[0];
50
6.56k
  uint8_t config2 = data[1];
51
6.56k
  int base_type = (config & 0x01) ? muBASETYPE_INT : muBASETYPE_FLOAT;
52
  
53
6.56k
  muParserHandle_t hParser = mupCreate(base_type);
54
6.56k
  if (!hParser) return 0;
55
56
  // Remaining data as expression
57
6.56k
  size_t expr_size = (size - 2) / 2;
58
6.56k
  std::string expr((char *)(data + 2), expr_size);
59
6.56k
  mupSetExpr(hParser, expr.c_str());
60
61
6.56k
  std::string custom_chars((char *)(data + 2 + expr_size), size - 2 - expr_size);
62
63
  // Conditional configurations based on config bits
64
6.56k
  if (config & 0x02) {
65
3.46k
    mupDefineInfixOprt(hParser, "!", MyInfixFun, 0, 1);
66
3.46k
  }
67
6.56k
  if (config & 0x04) {
68
3.46k
    mupDefinePostfixOprt(hParser, "!!", MyPostfixFun, 1);
69
3.46k
  }
70
6.56k
  if (config & 0x08) {
71
3.44k
    mupDefineOprt(hParser, "shr", MyOprtFun, 0, muOPRT_ASCT_LEFT, 1);
72
3.44k
  }
73
6.56k
  if (config & 0x10) {
74
5.58k
    mupSetVarFactory(hParser, MyVarFactory, NULL);
75
5.58k
  }
76
6.56k
  if (config & 0x20) {
77
5.25k
    mupAddValIdent(hParser, MyIdentFun);
78
5.25k
  }
79
  
80
6.56k
  if (!custom_chars.empty()) {
81
6.56k
    if (config & 0x40) {
82
1.74k
      mupDefineNameChars(hParser, custom_chars.c_str());
83
1.74k
    }
84
6.56k
    if (config & 0x80) {
85
1.53k
      mupDefineOprtChars(hParser, custom_chars.c_str());
86
1.53k
    }
87
6.56k
  }
88
89
  // Set some common things anyway
90
6.56k
  muFloat_t v1[10] = {1.0};
91
6.56k
  mupDefineVar(hParser, "v1", v1);
92
6.56k
  mupDefineConst(hParser, "c1", 3.14);
93
6.56k
  mupDefineStrConst(hParser, "s1", "hello");
94
  
95
  // From c_api_fuzzer.cc
96
6.56k
  mupDefineFun1(hParser, "f1", MyFun1, 1);
97
6.56k
  mupDefineFun2(hParser, "f2", MyFun2, 1);
98
99
  // Evaluate
100
6.56k
  try {
101
6.56k
    if (config2 & 0x01) {
102
      // Bulk mode evaluation
103
3.38k
      muFloat_t results[10];
104
3.38k
      mupEvalBulk(hParser, results, 10);
105
3.38k
    } else {
106
3.18k
      mupEval(hParser);
107
      
108
      // Try mupEvalMulti only if no error occurred in mupEval
109
3.18k
      if (!mupError(hParser)) {
110
1.09k
        int nNum;
111
1.09k
        mupEvalMulti(hParser, &nNum);
112
1.09k
      }
113
3.18k
    }
114
6.56k
  } catch (...) {
115
0
  }
116
117
  // Error handling
118
6.56k
  if (mupError(hParser)) {
119
1.88k
    mupGetErrorCode(hParser);
120
1.88k
    mupGetErrorPos(hParser);
121
1.88k
    mupGetErrorMsg(hParser);
122
1.88k
    mupGetErrorToken(hParser);
123
1.88k
  }
124
125
6.56k
  mupRelease(hParser);
126
6.56k
  return 0;
127
6.56k
}