Coverage Report

Created: 2025-12-22 06:51

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/mruby/oss-fuzz/proto_to_ruby.cpp
Line
Count
Source
1
#include "proto_to_ruby.h"
2
3
using namespace ruby_fuzzer;
4
5
std::string protoConverter::removeSpecial(const std::string &x)
6
738k
{
7
738k
  std::string tmp(x);
8
738k
  if (!tmp.empty())
9
46.7k
    tmp.erase(std::remove_if(tmp.begin(), tmp.end(),
10
6.92M
                             [](char c) { return !(std::isalpha(c) || std::isdigit(c)); } ), tmp.end());
11
738k
  return tmp;
12
738k
}
13
14
void protoConverter::visit(ArrType const& x)
15
34.7k
{
16
34.7k
  if (x.elements_size() > 0) {
17
4.44k
    int i = x.elements_size();
18
4.44k
    m_output << "[";
19
386k
    for (auto &e : x.elements()) {
20
386k
      i--;
21
386k
      if (i == 0) {
22
4.44k
        visit(e);
23
382k
      } else {
24
382k
        visit(e);
25
382k
        m_output << ", ";
26
382k
      }
27
386k
    }
28
4.44k
    m_output << "]";
29
30.2k
  } else {
30
30.2k
    m_output << "[1]";
31
30.2k
  }
32
34.7k
}
33
34
void protoConverter::visit(Array const& x)
35
34.7k
{
36
34.7k
  switch (x.arr_func()) {
37
10.3k
    case Array::FLATTEN:
38
10.3k
      visit(x.arr_arg());
39
10.3k
      m_output << ".flatten";
40
10.3k
      break;
41
6
    case Array::COMPACT:
42
6
      visit(x.arr_arg());
43
6
      m_output << ".compact";
44
6
      break;
45
243
    case Array::FETCH:
46
243
      visit(x.arr_arg());
47
243
      m_output << ".fetch";
48
243
      break;
49
3.65k
    case Array::FILL:
50
3.65k
      visit(x.arr_arg());
51
3.65k
      m_output << ".fill";
52
3.65k
      break;
53
915
    case Array::ROTATE:
54
915
      visit(x.arr_arg());
55
915
      m_output << ".rotate";
56
915
      break;
57
613
    case Array::ROTATE_E:
58
613
      visit(x.arr_arg());
59
613
      m_output << ".rotate!";
60
613
      break;
61
9
    case Array::DELETEIF:
62
9
      visit(x.arr_arg());
63
9
      m_output << ".delete_if";
64
9
      break;
65
882
    case Array::INSERT:
66
882
      visit(x.arr_arg());
67
882
      m_output << ".insert";
68
882
      break;
69
15
    case Array::BSEARCH:
70
15
      visit(x.arr_arg());
71
15
      m_output << ".bsearch";
72
15
      break;
73
9
    case Array::KEEPIF:
74
9
      visit(x.arr_arg());
75
9
      m_output << ".keep_if";
76
9
      break;
77
75
    case Array::SELECT:
78
75
      visit(x.arr_arg());
79
75
      m_output << ".select";
80
75
      break;
81
711
    case Array::VALUES_AT:
82
711
      visit(x.arr_arg());
83
711
      m_output << ".values_at";
84
711
      break;
85
747
    case Array::BLOCK:
86
747
      visit(x.arr_arg());
87
747
      m_output << ".index";
88
747
      break;
89
876
    case Array::DIG:
90
876
      visit(x.arr_arg());
91
876
      m_output << ".dig";
92
876
      break;
93
571
    case Array::SLICE:
94
571
      visit(x.arr_arg());
95
571
      m_output << ".slice";
96
571
      break;
97
1.91k
    case Array::PERM:
98
1.91k
      visit(x.arr_arg());
99
1.91k
      m_output << ".permutation";
100
1.91k
      break;
101
12.9k
    case Array::COMB:
102
12.9k
      visit(x.arr_arg());
103
12.9k
      m_output << ".combination";
104
12.9k
      break;
105
52
    case Array::ASSOC:
106
52
      visit(x.arr_arg());
107
52
      m_output << ".assoc";
108
52
      break;
109
128
    case Array::RASSOC:
110
128
      visit(x.arr_arg());
111
128
      m_output << ".rassoc";
112
128
      break;
113
34.7k
  }
114
34.7k
  m_output << "(";
115
34.7k
  visit(x.val_arg());
116
34.7k
  m_output << ")";
117
34.7k
}
118
119
void protoConverter::visit(AssignmentStatement const& x)
120
212k
{
121
212k
  m_output << "var_" << m_numLiveVars << " = ";
122
212k
  visit(x.rvalue());
123
212k
  m_numVarsPerScope.top()++;
124
212k
  m_numLiveVars++;
125
212k
  m_output << "\n";
126
212k
}
127
128
void protoConverter::visit(BinaryOp const& x)
129
187k
{
130
187k
  m_output << "(";
131
187k
  visit(x.left());
132
187k
  switch (x.op()) {
133
46.2k
    case BinaryOp::ADD: m_output << " + "; break;
134
40.8k
    case BinaryOp::SUB: m_output << " - "; break;
135
30.9k
    case BinaryOp::MUL: m_output << " * "; break;
136
15.3k
    case BinaryOp::DIV: m_output << " / "; break;
137
6.90k
    case BinaryOp::MOD: m_output << " % "; break;
138
7.79k
    case BinaryOp::XOR: m_output << " ^ "; break;
139
9.20k
    case BinaryOp::AND: m_output << " and "; break;
140
2.60k
    case BinaryOp::OR: m_output << " or "; break;
141
3.89k
    case BinaryOp::EQ: m_output << " == "; break;
142
4.46k
    case BinaryOp::NE: m_output << " != "; break;
143
2.77k
    case BinaryOp::LE: m_output << " <= "; break;
144
1.21k
    case BinaryOp::GE: m_output << " >= "; break;
145
1.03k
    case BinaryOp::LT: m_output << " < "; break;
146
1.77k
    case BinaryOp::GT: m_output << " > "; break;
147
12.8k
    case BinaryOp::RS: m_output << " >> "; break;
148
187k
  }
149
187k
  visit(x.right());
150
187k
  m_output << ")";
151
187k
}
152
153
void protoConverter::visit(BuiltinFuncs const& x)
154
69.9k
{
155
69.9k
  switch (x.bifunc_oneof_case()) {
156
9.54k
    case BuiltinFuncs::kOs:
157
9.54k
      visit(x.os());
158
9.54k
      break;
159
4.45k
    case BuiltinFuncs::kTime:
160
4.45k
      visit(x.time());
161
4.45k
      break;
162
34.7k
    case BuiltinFuncs::kArr:
163
34.7k
      visit(x.arr());
164
34.7k
      break;
165
9.35k
    case BuiltinFuncs::kMops:
166
9.35k
      visit(x.mops());
167
9.35k
      break;
168
11.9k
    case BuiltinFuncs::BIFUNC_ONEOF_NOT_SET:
169
11.9k
      m_output << "1";
170
11.9k
      break;
171
69.9k
  }
172
69.9k
  m_output << "\n";
173
69.9k
}
174
175
void protoConverter::visit(Const const& x)
176
437k
{
177
437k
  switch (x.const_oneof_case()) {
178
44.7k
    case Const::kIntLit:
179
44.7k
      m_output << "(" << (x.int_lit() % 13) << ")";
180
44.7k
      break;
181
15.5k
    case Const::kBoolVal:
182
15.5k
      m_output << "(" << x.bool_val() << ")";
183
15.5k
      break;
184
377k
    case Const::CONST_ONEOF_NOT_SET:
185
377k
      m_output << "1";
186
377k
      break;
187
437k
  }
188
437k
}
189
190
void protoConverter::visit(Function const& x)
191
916
{
192
916
  m_output << "def foo()\nvar_0 = 1\n";
193
916
  visit(x.statements());
194
916
  m_output << "end\n";
195
916
  m_output << "foo\n";
196
916
}
197
198
void protoConverter::visit(HashType const& x)
199
9.54k
{
200
9.54k
  if (x.keyval_size() > 0) {
201
3.20k
    int i = x.keyval_size();
202
3.20k
    m_output << "{";
203
369k
    for (auto &e : x.keyval()) {
204
369k
      i--;
205
369k
      if (i == 0) {
206
3.20k
        visit(e);
207
3.20k
      }
208
365k
      else {
209
365k
        visit(e);
210
365k
        m_output << ", ";
211
365k
      }
212
369k
    }
213
3.20k
    m_output << "}";
214
3.20k
  }
215
9.54k
}
216
217
void protoConverter::visit(IfElse const& x)
218
17.1k
{
219
17.1k
  m_output << "if ";
220
17.1k
  visit(x.cond());
221
17.1k
  m_output << "\n";
222
17.1k
  visit(x.if_body());
223
17.1k
  m_output << "\nelse\n";
224
17.1k
  visit(x.else_body());
225
17.1k
  m_output << "\nend\n";
226
17.1k
}
227
228
void protoConverter::visit(KVPair const& x)
229
369k
{
230
369k
  m_output << "\"" << removeSpecial(x.key()) << "\"";
231
369k
  m_output << " => ";
232
369k
  m_output << "\"" << removeSpecial(x.val()) << "\"";
233
369k
}
234
235
void protoConverter::visit(MathConst const& x)
236
5.94k
{
237
5.94k
  switch (x.math_const()) {
238
1.28k
    case MathConst::PI:
239
1.28k
      m_output << "Math::PI";
240
1.28k
      break;
241
4.66k
    case MathConst::E:
242
4.66k
      m_output << "Math::E";
243
4.66k
      break;
244
5.94k
  }
245
5.94k
}
246
247
void protoConverter::visit(MathOps const& x)
248
9.35k
{
249
9.35k
  switch (x.math_op()) {
250
1.52k
    case MathOps::CBRT:
251
1.52k
      m_output << "Math.cbrt(";
252
1.52k
      visit(x.math_arg());
253
1.52k
      m_output << ")";
254
1.52k
      break;
255
418
    case MathOps::COS:
256
418
      m_output << "Math.cos(";
257
418
      visit(x.math_arg());
258
418
      m_output << ")";
259
418
      break;
260
2.16k
    case MathOps::ERF:
261
2.16k
      m_output << "Math.erf(";
262
2.16k
      visit(x.math_arg());
263
2.16k
      m_output << ")";
264
2.16k
      break;
265
354
    case MathOps::ERFC:
266
354
      m_output << "Math.erfc(";
267
354
      visit(x.math_arg());
268
354
      m_output << ")";
269
354
      break;
270
2.06k
    case MathOps::LOG:
271
2.06k
      m_output << "Math.log(";
272
2.06k
      visit(x.math_arg());
273
2.06k
      m_output << ")";
274
2.06k
      break;
275
285
    case MathOps::LOG10:
276
285
      m_output << "Math.log10(";
277
285
      visit(x.math_arg());
278
285
      m_output << ")";
279
285
      break;
280
379
    case MathOps::LOG2:
281
379
      m_output << "Math.log2(";
282
379
      visit(x.math_arg());
283
379
      m_output << ")";
284
379
      break;
285
849
    case MathOps::SIN:
286
849
      m_output << "Math.sin(";
287
849
      visit(x.math_arg());
288
849
      m_output << ")";
289
849
      break;
290
544
    case MathOps::SQRT:
291
544
      m_output << "Math.sqrt(";
292
544
      visit(x.math_arg());
293
544
      m_output << ")";
294
544
      break;
295
783
    case MathOps::TAN:
296
783
      m_output << "Math.tan(";
297
783
      visit(x.math_arg());
298
783
      m_output << ")";
299
783
      break;
300
9.35k
  }
301
9.35k
}
302
303
void protoConverter::visit(MathType const& x)
304
9.35k
{
305
9.35k
  switch (x.math_arg_oneof_case()) {
306
1.32k
    case MathType::kMathRval:
307
1.32k
      visit(x.math_rval());
308
1.32k
      break;
309
5.94k
    case MathType::kMathConst:
310
5.94k
      visit(x.math_const());
311
5.94k
      break;
312
2.09k
    case MathType::MATH_ARG_ONEOF_NOT_SET:
313
2.09k
      m_output << "1";
314
2.09k
      break;
315
9.35k
  }
316
9.35k
}
317
318
void protoConverter::visit(ObjectSpace const& x)
319
9.54k
{
320
9.54k
  switch (x.os_func()) {
321
9.54k
    case ObjectSpace::COUNT:
322
9.54k
      m_output << "ObjectSpace.count_objects";
323
9.54k
      break;
324
9.54k
  }
325
9.54k
  m_output << "(";
326
9.54k
  visit(x.os_arg());
327
9.54k
  m_output << ")" << "\n";
328
9.54k
}
329
330
void protoConverter::visit(Rvalue const& x)
331
660k
{
332
660k
  switch (x.rvalue_oneof_case()) {
333
106k
    case Rvalue::kVarref:
334
106k
      visit(x.varref());
335
106k
      break;
336
50.6k
    case Rvalue::kCons:
337
50.6k
      visit(x.cons());
338
50.6k
      break;
339
187k
    case Rvalue::kBinop:
340
187k
      visit(x.binop());
341
187k
      break;
342
315k
    case Rvalue::RVALUE_ONEOF_NOT_SET:
343
315k
      m_output << "1";
344
315k
      break;
345
660k
  }
346
660k
}
347
348
void protoConverter::visit(Statement const& x)
349
420k
{
350
420k
  switch (x.stmt_oneof_case()) {
351
212k
    case Statement::kAssignment:
352
212k
      visit(x.assignment());
353
212k
      break;
354
17.1k
    case Statement::kIfelse:
355
17.1k
      visit(x.ifelse());
356
17.1k
      break;
357
6.34k
    case Statement::kTernaryStmt:
358
6.34k
      visit(x.ternary_stmt());
359
6.34k
      break;
360
69.9k
    case Statement::kBuiltins:
361
69.9k
      visit(x.builtins());
362
69.9k
      break;
363
16.0k
    case Statement::kBlockstmt:
364
16.0k
      visit(x.blockstmt());
365
16.0k
      break;
366
98.9k
    case Statement::STMT_ONEOF_NOT_SET:
367
98.9k
      break;
368
420k
  }
369
420k
  m_output << "\n";
370
420k
}
371
372
void protoConverter::visit(StatementSeq const& x)
373
51.2k
{
374
51.2k
  if (x.statements_size() > 0) {
375
18.8k
    m_numVarsPerScope.push(0);
376
18.8k
    m_output << "@scope ||= begin\n";
377
18.8k
    for (auto &st : x.statements())
378
420k
      visit(st);
379
18.8k
    m_output << "end\n";
380
18.8k
    m_numLiveVars -= m_numVarsPerScope.top();
381
18.8k
    m_numVarsPerScope.pop();
382
18.8k
  }
383
51.2k
}
384
385
void protoConverter::visit(StringExtNoArg const& x)
386
0
{
387
0
  m_output << "\"" << removeSpecial(x.str_arg()) << "\"";
388
0
  switch (x.str_op()) {
389
0
    case StringExtNoArg::DUMP:
390
0
      m_output << ".dump";
391
0
      break;
392
0
    case StringExtNoArg::STRIP:
393
0
      m_output << ".strip";
394
0
      break;
395
0
    case StringExtNoArg::LSTRIP:
396
0
      m_output << ".lstrip";
397
0
      break;
398
0
    case StringExtNoArg::RSTRIP:
399
0
      m_output << ".rstrip";
400
0
      break;
401
0
    case StringExtNoArg::STRIPE:
402
0
      m_output << ".strip!";
403
0
      break;
404
0
    case StringExtNoArg::LSTRIPE:
405
0
      m_output << ".lstrip!";
406
0
      break;
407
0
    case StringExtNoArg::RSTRIPE:
408
0
      m_output << ".rstrip!";
409
0
      break;
410
0
    case StringExtNoArg::SWAPCASE:
411
0
      m_output << ".swapcase";
412
0
      break;
413
0
    case StringExtNoArg::SWAPCASEE:
414
0
      m_output << ".swapcase!";
415
0
      break;
416
0
    case StringExtNoArg::SQUEEZE:
417
0
      m_output << ".squeeze";
418
0
      break;
419
0
  }
420
0
}
421
422
void protoConverter::visit(Ternary const& x)
423
6.34k
{
424
6.34k
  m_output << "(";
425
6.34k
  visit(x.tern_cond());
426
6.34k
  m_output << " ? ";
427
6.34k
  visit(x.t_branch());
428
6.34k
  m_output << " : ";
429
6.34k
  visit(x.f_branch());
430
6.34k
  m_output << ")\n";
431
6.34k
}
432
433
void protoConverter::visit(Time const& x)
434
4.45k
{
435
4.45k
  switch (x.t_func()) {
436
2.60k
    case Time::AT:
437
2.60k
      m_output << "Time.at";
438
2.60k
      break;
439
1.84k
    case Time::GM:
440
1.84k
      m_output << "Time.gm";
441
1.84k
      break;
442
4.45k
  }
443
4.45k
  m_output << "(" << (x.t_arg()% 13) << ")" << "\n";
444
4.45k
}
445
446
void protoConverter::visit(VarRef const& x)
447
106k
{
448
106k
  m_output << "var_" << (static_cast<uint32_t>(x.varnum()) % m_numLiveVars);
449
106k
}
450
451
std::string protoConverter::FunctionToString(Function const& input)
452
916
{
453
916
  visit(input);
454
916
  return m_output.str();
455
916
}