Coverage Report

Created: 2023-09-25 06:17

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