Coverage Report

Created: 2026-09-28 06:21

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
214
muFloat_t MyFun1(muFloat_t v) { return v * 2; }
26
226
muFloat_t MyFun2(muFloat_t v1, muFloat_t v2) { return v1 + v2; }
27
130k
muFloat_t MyInfixFun(muFloat_t v) { return -v; }
28
4.68k
muFloat_t MyPostfixFun(muFloat_t v) { return v + 1; }
29
800
muFloat_t MyOprtFun(muFloat_t v1, muFloat_t v2) { return v1 * v2 + 1; }
30
31
26.7k
muFloat_t* MyVarFactory(const muChar_t* name, void* pUserData) {
32
26.7k
  static muFloat_t v[10];
33
26.7k
  return v;
34
26.7k
}
35
36
743k
muInt_t MyIdentFun(const muChar_t* name, muInt_t* pos, muFloat_t* val) {
37
743k
  if (strncmp(name, "test", 4) == 0) {
38
279
    *val = 123.0;
39
279
    *pos += 4;
40
279
    return 1;
41
279
  }
42
743k
  return 0;
43
743k
}
44
45
6.39k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
46
6.39k
  if (size < 10) return 0;
47
48
  // Use the first few bytes for configuration
49
6.38k
  uint8_t config = data[0];
50
6.38k
  uint8_t config2 = data[1];
51
6.38k
  int base_type = (config & 0x01) ? muBASETYPE_INT : muBASETYPE_FLOAT;
52
  
53
6.38k
  muParserHandle_t hParser = mupCreate(base_type);
54
6.38k
  if (!hParser) return 0;
55
56
  // Remaining data as expression
57
6.38k
  size_t expr_size = (size - 2) / 2;
58
6.38k
  std::string expr((char *)(data + 2), expr_size);
59
6.38k
  mupSetExpr(hParser, expr.c_str());
60
61
6.38k
  std::string custom_chars((char *)(data + 2 + expr_size), size - 2 - expr_size);
62
63
  // Conditional configurations based on config bits
64
6.38k
  if (config & 0x02) {
65
3.62k
    mupDefineInfixOprt(hParser, "!", MyInfixFun, 0, 1);
66
3.62k
  }
67
6.38k
  if (config & 0x04) {
68
3.55k
    mupDefinePostfixOprt(hParser, "!!", MyPostfixFun, 1);
69
3.55k
  }
70
6.38k
  if (config & 0x08) {
71
3.34k
    mupDefineOprt(hParser, "shr", MyOprtFun, 0, muOPRT_ASCT_LEFT, 1);
72
3.34k
  }
73
6.38k
  if (config & 0x10) {
74
5.42k
    mupSetVarFactory(hParser, MyVarFactory, NULL);
75
5.42k
  }
76
6.38k
  if (config & 0x20) {
77
5.05k
    mupAddValIdent(hParser, MyIdentFun);
78
5.05k
  }
79
  
80
6.38k
  if (!custom_chars.empty()) {
81
6.38k
    if (config & 0x40) {
82
1.62k
      mupDefineNameChars(hParser, custom_chars.c_str());
83
1.62k
    }
84
6.38k
    if (config & 0x80) {
85
1.52k
      mupDefineOprtChars(hParser, custom_chars.c_str());
86
1.52k
    }
87
6.38k
  }
88
89
  // Set some common things anyway
90
6.38k
  muFloat_t v1[10] = {1.0};
91
6.38k
  mupDefineVar(hParser, "v1", v1);
92
6.38k
  mupDefineConst(hParser, "c1", 3.14);
93
6.38k
  mupDefineStrConst(hParser, "s1", "hello");
94
  
95
  // From c_api_fuzzer.cc
96
6.38k
  mupDefineFun1(hParser, "f1", MyFun1, 1);
97
6.38k
  mupDefineFun2(hParser, "f2", MyFun2, 1);
98
99
  // Evaluate
100
6.38k
  try {
101
6.38k
    if (config2 & 0x01) {
102
      // Bulk mode evaluation
103
3.18k
      muFloat_t results[10];
104
3.18k
      mupEvalBulk(hParser, results, 10);
105
3.19k
    } else {
106
3.19k
      mupEval(hParser);
107
      
108
      // Try mupEvalMulti only if no error occurred in mupEval
109
3.19k
      if (!mupError(hParser)) {
110
1.11k
        int nNum;
111
1.11k
        mupEvalMulti(hParser, &nNum);
112
1.11k
      }
113
3.19k
    }
114
6.38k
  } catch (...) {
115
0
  }
116
117
  // Error handling
118
6.38k
  if (mupError(hParser)) {
119
1.83k
    mupGetErrorCode(hParser);
120
1.83k
    mupGetErrorPos(hParser);
121
1.83k
    mupGetErrorMsg(hParser);
122
1.83k
    mupGetErrorToken(hParser);
123
1.83k
  }
124
125
6.38k
  mupRelease(hParser);
126
6.38k
  return 0;
127
6.38k
}