Coverage Report

Created: 2026-05-30 06:46

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