Coverage Report

Created: 2026-06-10 06:31

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