Coverage Report

Created: 2025-06-24 06:48

/src/mruby/oss-fuzz/proto_to_ruby.cpp
Line
Count
Source (jump to first uncovered line)
1
#include "proto_to_ruby.h"
2
3
using namespace ruby_fuzzer;
4
5
std::string protoConverter::removeSpecial(const std::string &x)
6
637k
{
7
637k
  std::string tmp(x);
8
637k
  if (!tmp.empty())
9
83.2k
    tmp.erase(std::remove_if(tmp.begin(), tmp.end(),
10
9.06M
                             [](char c) { return !(std::isalpha(c) || std::isdigit(c)); } ), tmp.end());
11
637k
  return tmp;
12
637k
}
13
14
void protoConverter::visit(ArrType const& x)
15
73.5k
{
16
73.5k
  if (x.elements_size() > 0) {
17
13.0k
    int i = x.elements_size();
18
13.0k
    m_output << "[";
19
492k
    for (auto &e : x.elements()) {
20
492k
      i--;
21
492k
      if (i == 0) {
22
13.0k
        visit(e);
23
479k
      } else {
24
479k
        visit(e);
25
479k
        m_output << ", ";
26
479k
      }
27
492k
    }
28
13.0k
    m_output << "]";
29
60.4k
  } else {
30
60.4k
    m_output << "[1]";
31
60.4k
  }
32
73.5k
}
33
34
void protoConverter::visit(Array const& x)
35
73.5k
{
36
73.5k
  switch (x.arr_func()) {
37
11.8k
    case Array::FLATTEN:
38
11.8k
      visit(x.arr_arg());
39
11.8k
      m_output << ".flatten";
40
11.8k
      break;
41
80
    case Array::COMPACT:
42
80
      visit(x.arr_arg());
43
80
      m_output << ".compact";
44
80
      break;
45
901
    case Array::FETCH:
46
901
      visit(x.arr_arg());
47
901
      m_output << ".fetch";
48
901
      break;
49
1.40k
    case Array::FILL:
50
1.40k
      visit(x.arr_arg());
51
1.40k
      m_output << ".fill";
52
1.40k
      break;
53
1.58k
    case Array::ROTATE:
54
1.58k
      visit(x.arr_arg());
55
1.58k
      m_output << ".rotate";
56
1.58k
      break;
57
1.38k
    case Array::ROTATE_E:
58
1.38k
      visit(x.arr_arg());
59
1.38k
      m_output << ".rotate!";
60
1.38k
      break;
61
77
    case Array::DELETEIF:
62
77
      visit(x.arr_arg());
63
77
      m_output << ".delete_if";
64
77
      break;
65
2.42k
    case Array::INSERT:
66
2.42k
      visit(x.arr_arg());
67
2.42k
      m_output << ".insert";
68
2.42k
      break;
69
163
    case Array::BSEARCH:
70
163
      visit(x.arr_arg());
71
163
      m_output << ".bsearch";
72
163
      break;
73
148
    case Array::KEEPIF:
74
148
      visit(x.arr_arg());
75
148
      m_output << ".keep_if";
76
148
      break;
77
217
    case Array::SELECT:
78
217
      visit(x.arr_arg());
79
217
      m_output << ".select";
80
217
      break;
81
1.79k
    case Array::VALUES_AT:
82
1.79k
      visit(x.arr_arg());
83
1.79k
      m_output << ".values_at";
84
1.79k
      break;
85
3.91k
    case Array::BLOCK:
86
3.91k
      visit(x.arr_arg());
87
3.91k
      m_output << ".index";
88
3.91k
      break;
89
1.95k
    case Array::DIG:
90
1.95k
      visit(x.arr_arg());
91
1.95k
      m_output << ".dig";
92
1.95k
      break;
93
1.06k
    case Array::SLICE:
94
1.06k
      visit(x.arr_arg());
95
1.06k
      m_output << ".slice";
96
1.06k
      break;
97
4.87k
    case Array::PERM:
98
4.87k
      visit(x.arr_arg());
99
4.87k
      m_output << ".permutation";
100
4.87k
      break;
101
37.9k
    case Array::COMB:
102
37.9k
      visit(x.arr_arg());
103
37.9k
      m_output << ".combination";
104
37.9k
      break;
105
759
    case Array::ASSOC:
106
759
      visit(x.arr_arg());
107
759
      m_output << ".assoc";
108
759
      break;
109
1.01k
    case Array::RASSOC:
110
1.01k
      visit(x.arr_arg());
111
1.01k
      m_output << ".rassoc";
112
1.01k
      break;
113
73.5k
  }
114
73.5k
  m_output << "(";
115
73.5k
  visit(x.val_arg());
116
73.5k
  m_output << ")";
117
73.5k
}
118
119
void protoConverter::visit(AssignmentStatement const& x)
120
306k
{
121
306k
  m_output << "var_" << m_numLiveVars << " = ";
122
306k
  visit(x.rvalue());
123
306k
  m_numVarsPerScope.top()++;
124
306k
  m_numLiveVars++;
125
306k
  m_output << "\n";
126
306k
}
127
128
void protoConverter::visit(BinaryOp const& x)
129
260k
{
130
260k
  m_output << "(";
131
260k
  visit(x.left());
132
260k
  switch (x.op()) {
133
42.5k
    case BinaryOp::ADD: m_output << " + "; break;
134
62.2k
    case BinaryOp::SUB: m_output << " - "; break;
135
37.3k
    case BinaryOp::MUL: m_output << " * "; break;
136
18.8k
    case BinaryOp::DIV: m_output << " / "; break;
137
12.1k
    case BinaryOp::MOD: m_output << " % "; break;
138
20.3k
    case BinaryOp::XOR: m_output << " ^ "; break;
139
9.00k
    case BinaryOp::AND: m_output << " and "; break;
140
5.32k
    case BinaryOp::OR: m_output << " or "; break;
141
3.18k
    case BinaryOp::EQ: m_output << " == "; break;
142
9.18k
    case BinaryOp::NE: m_output << " != "; break;
143
4.24k
    case BinaryOp::LE: m_output << " <= "; break;
144
4.87k
    case BinaryOp::GE: m_output << " >= "; break;
145
2.23k
    case BinaryOp::LT: m_output << " < "; break;
146
3.26k
    case BinaryOp::GT: m_output << " > "; break;
147
25.9k
    case BinaryOp::RS: m_output << " >> "; break;
148
260k
  }
149
260k
  visit(x.right());
150
260k
  m_output << ")";
151
260k
}
152
153
void protoConverter::visit(BuiltinFuncs const& x)
154
184k
{
155
184k
  switch (x.bifunc_oneof_case()) {
156
20.2k
    case BuiltinFuncs::kOs:
157
20.2k
      visit(x.os());
158
20.2k
      break;
159
15.0k
    case BuiltinFuncs::kTime:
160
15.0k
      visit(x.time());
161
15.0k
      break;
162
73.5k
    case BuiltinFuncs::kArr:
163
73.5k
      visit(x.arr());
164
73.5k
      break;
165
44.4k
    case BuiltinFuncs::kMops:
166
44.4k
      visit(x.mops());
167
44.4k
      break;
168
30.8k
    case BuiltinFuncs::BIFUNC_ONEOF_NOT_SET:
169
30.8k
      m_output << "1";
170
30.8k
      break;
171
184k
  }
172
184k
  m_output << "\n";
173
184k
}
174
175
void protoConverter::visit(Const const& x)
176
579k
{
177
579k
  switch (x.const_oneof_case()) {
178
79.2k
    case Const::kIntLit:
179
79.2k
      m_output << "(" << (x.int_lit() % 13) << ")";
180
79.2k
      break;
181
30.1k
    case Const::kBoolVal:
182
30.1k
      m_output << "(" << x.bool_val() << ")";
183
30.1k
      break;
184
469k
    case Const::CONST_ONEOF_NOT_SET:
185
469k
      m_output << "1";
186
469k
      break;
187
579k
  }
188
579k
}
189
190
void protoConverter::visit(Function const& x)
191
2.10k
{
192
2.10k
  m_output << "def foo()\nvar_0 = 1\n";
193
2.10k
  visit(x.statements());
194
2.10k
  m_output << "end\n";
195
2.10k
  m_output << "foo\n";
196
2.10k
}
197
198
void protoConverter::visit(HashType const& x)
199
20.2k
{
200
20.2k
  if (x.keyval_size() > 0) {
201
6.67k
    int i = x.keyval_size();
202
6.67k
    m_output << "{";
203
318k
    for (auto &e : x.keyval()) {
204
318k
      i--;
205
318k
      if (i == 0) {
206
6.67k
        visit(e);
207
6.67k
      }
208
311k
      else {
209
311k
        visit(e);
210
311k
        m_output << ", ";
211
311k
      }
212
318k
    }
213
6.67k
    m_output << "}";
214
6.67k
  }
215
20.2k
}
216
217
void protoConverter::visit(IfElse const& x)
218
34.9k
{
219
34.9k
  m_output << "if ";
220
34.9k
  visit(x.cond());
221
34.9k
  m_output << "\n";
222
34.9k
  visit(x.if_body());
223
34.9k
  m_output << "\nelse\n";
224
34.9k
  visit(x.else_body());
225
34.9k
  m_output << "\nend\n";
226
34.9k
}
227
228
void protoConverter::visit(KVPair const& x)
229
318k
{
230
318k
  m_output << "\"" << removeSpecial(x.key()) << "\"";
231
318k
  m_output << " => ";
232
318k
  m_output << "\"" << removeSpecial(x.val()) << "\"";
233
318k
}
234
235
void protoConverter::visit(MathConst const& x)
236
29.0k
{
237
29.0k
  switch (x.math_const()) {
238
8.51k
    case MathConst::PI:
239
8.51k
      m_output << "Math::PI";
240
8.51k
      break;
241
20.5k
    case MathConst::E:
242
20.5k
      m_output << "Math::E";
243
20.5k
      break;
244
29.0k
  }
245
29.0k
}
246
247
void protoConverter::visit(MathOps const& x)
248
44.4k
{
249
44.4k
  switch (x.math_op()) {
250
6.98k
    case MathOps::CBRT:
251
6.98k
      m_output << "Math.cbrt(";
252
6.98k
      visit(x.math_arg());
253
6.98k
      m_output << ")";
254
6.98k
      break;
255
1.28k
    case MathOps::COS:
256
1.28k
      m_output << "Math.cos(";
257
1.28k
      visit(x.math_arg());
258
1.28k
      m_output << ")";
259
1.28k
      break;
260
3.29k
    case MathOps::ERF:
261
3.29k
      m_output << "Math.erf(";
262
3.29k
      visit(x.math_arg());
263
3.29k
      m_output << ")";
264
3.29k
      break;
265
611
    case MathOps::ERFC:
266
611
      m_output << "Math.erfc(";
267
611
      visit(x.math_arg());
268
611
      m_output << ")";
269
611
      break;
270
5.92k
    case MathOps::LOG:
271
5.92k
      m_output << "Math.log(";
272
5.92k
      visit(x.math_arg());
273
5.92k
      m_output << ")";
274
5.92k
      break;
275
898
    case MathOps::LOG10:
276
898
      m_output << "Math.log10(";
277
898
      visit(x.math_arg());
278
898
      m_output << ")";
279
898
      break;
280
6.99k
    case MathOps::LOG2:
281
6.99k
      m_output << "Math.log2(";
282
6.99k
      visit(x.math_arg());
283
6.99k
      m_output << ")";
284
6.99k
      break;
285
1.99k
    case MathOps::SIN:
286
1.99k
      m_output << "Math.sin(";
287
1.99k
      visit(x.math_arg());
288
1.99k
      m_output << ")";
289
1.99k
      break;
290
7.14k
    case MathOps::SQRT:
291
7.14k
      m_output << "Math.sqrt(";
292
7.14k
      visit(x.math_arg());
293
7.14k
      m_output << ")";
294
7.14k
      break;
295
9.27k
    case MathOps::TAN:
296
9.27k
      m_output << "Math.tan(";
297
9.27k
      visit(x.math_arg());
298
9.27k
      m_output << ")";
299
9.27k
      break;
300
44.4k
  }
301
44.4k
}
302
303
void protoConverter::visit(MathType const& x)
304
44.4k
{
305
44.4k
  switch (x.math_arg_oneof_case()) {
306
2.66k
    case MathType::kMathRval:
307
2.66k
      visit(x.math_rval());
308
2.66k
      break;
309
29.0k
    case MathType::kMathConst:
310
29.0k
      visit(x.math_const());
311
29.0k
      break;
312
12.7k
    case MathType::MATH_ARG_ONEOF_NOT_SET:
313
12.7k
      m_output << "1";
314
12.7k
      break;
315
44.4k
  }
316
44.4k
}
317
318
void protoConverter::visit(ObjectSpace const& x)
319
20.2k
{
320
20.2k
  switch (x.os_func()) {
321
20.2k
    case ObjectSpace::COUNT:
322
20.2k
      m_output << "ObjectSpace.count_objects";
323
20.2k
      break;
324
20.2k
  }
325
20.2k
  m_output << "(";
326
20.2k
  visit(x.os_arg());
327
20.2k
  m_output << ")" << "\n";
328
20.2k
}
329
330
void protoConverter::visit(Rvalue const& x)
331
984k
{
332
984k
  switch (x.rvalue_oneof_case()) {
333
144k
    case Rvalue::kVarref:
334
144k
      visit(x.varref());
335
144k
      break;
336
86.8k
    case Rvalue::kCons:
337
86.8k
      visit(x.cons());
338
86.8k
      break;
339
260k
    case Rvalue::kBinop:
340
260k
      visit(x.binop());
341
260k
      break;
342
492k
    case Rvalue::RVALUE_ONEOF_NOT_SET:
343
492k
      m_output << "1";
344
492k
      break;
345
984k
  }
346
984k
}
347
348
void protoConverter::visit(Statement const& x)
349
783k
{
350
783k
  switch (x.stmt_oneof_case()) {
351
306k
    case Statement::kAssignment:
352
306k
      visit(x.assignment());
353
306k
      break;
354
34.9k
    case Statement::kIfelse:
355
34.9k
      visit(x.ifelse());
356
34.9k
      break;
357
15.1k
    case Statement::kTernaryStmt:
358
15.1k
      visit(x.ternary_stmt());
359
15.1k
      break;
360
184k
    case Statement::kBuiltins:
361
184k
      visit(x.builtins());
362
184k
      break;
363
43.5k
    case Statement::kBlockstmt:
364
43.5k
      visit(x.blockstmt());
365
43.5k
      break;
366
198k
    case Statement::STMT_ONEOF_NOT_SET:
367
198k
      break;
368
783k
  }
369
783k
  m_output << "\n";
370
783k
}
371
372
void protoConverter::visit(StatementSeq const& x)
373
115k
{
374
115k
  if (x.statements_size() > 0) {
375
51.3k
    m_numVarsPerScope.push(0);
376
51.3k
    m_output << "@scope ||= begin\n";
377
51.3k
    for (auto &st : x.statements())
378
783k
      visit(st);
379
51.3k
    m_output << "end\n";
380
51.3k
    m_numLiveVars -= m_numVarsPerScope.top();
381
51.3k
    m_numVarsPerScope.pop();
382
51.3k
  }
383
115k
}
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
15.1k
{
424
15.1k
  m_output << "(";
425
15.1k
  visit(x.tern_cond());
426
15.1k
  m_output << " ? ";
427
15.1k
  visit(x.t_branch());
428
15.1k
  m_output << " : ";
429
15.1k
  visit(x.f_branch());
430
15.1k
  m_output << ")\n";
431
15.1k
}
432
433
void protoConverter::visit(Time const& x)
434
15.0k
{
435
15.0k
  switch (x.t_func()) {
436
4.82k
    case Time::AT:
437
4.82k
      m_output << "Time.at";
438
4.82k
      break;
439
10.2k
    case Time::GM:
440
10.2k
      m_output << "Time.gm";
441
10.2k
      break;
442
15.0k
  }
443
15.0k
  m_output << "(" << (x.t_arg()% 13) << ")" << "\n";
444
15.0k
}
445
446
void protoConverter::visit(VarRef const& x)
447
144k
{
448
144k
  m_output << "var_" << (static_cast<uint32_t>(x.varnum()) % m_numLiveVars);
449
144k
}
450
451
std::string protoConverter::FunctionToString(Function const& input)
452
2.10k
{
453
2.10k
  visit(input);
454
2.10k
  return m_output.str();
455
2.10k
}