Skip to content

Commit 5777203

Browse files
committed
Add basic protection aginst circular references in pycdas and pycdc.
This fixes the last case of fuzzer errors detected by #572.
1 parent 38799f5 commit 5777203

File tree

2 files changed

+32
-0
lines changed

2 files changed

+32
-0
lines changed

ASTree.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include <cstring>
22
#include <cstdint>
33
#include <stdexcept>
4+
#include <unordered_set>
45
#include "ASTree.h"
56
#include "FastStack.h"
67
#include "pyc_numeric.h"
@@ -2779,6 +2780,8 @@ void print_formatted_value(PycRef<ASTFormattedValue> formatted_value, PycModule*
27792780
pyc_output << "}";
27802781
}
27812782

2783+
static std::unordered_set<ASTNode *> node_seen;
2784+
27822785
void print_src(PycRef<ASTNode> node, PycModule* mod, std::ostream& pyc_output)
27832786
{
27842787
if (node == NULL) {
@@ -2787,6 +2790,12 @@ void print_src(PycRef<ASTNode> node, PycModule* mod, std::ostream& pyc_output)
27872790
return;
27882791
}
27892792

2793+
if (node_seen.find((ASTNode *)node) != node_seen.end()) {
2794+
fputs("WARNING: Circular reference detected\n", stderr);
2795+
return;
2796+
}
2797+
node_seen.insert((ASTNode *)node);
2798+
27902799
switch (node->type()) {
27912800
case ASTNode::NODE_BINARY:
27922801
case ASTNode::NODE_COMPARE:
@@ -3442,10 +3451,12 @@ void print_src(PycRef<ASTNode> node, PycModule* mod, std::ostream& pyc_output)
34423451
pyc_output << "<NODE:" << node->type() << ">";
34433452
fprintf(stderr, "Unsupported Node type: %d\n", node->type());
34443453
cleanBuild = false;
3454+
node_seen.erase((ASTNode *)node);
34453455
return;
34463456
}
34473457

34483458
cleanBuild = true;
3459+
node_seen.erase((ASTNode *)node);
34493460
}
34503461

34513462
bool print_docstring(PycRef<PycObject> obj, int indent, PycModule* mod,
@@ -3462,8 +3473,16 @@ bool print_docstring(PycRef<PycObject> obj, int indent, PycModule* mod,
34623473
return false;
34633474
}
34643475

3476+
static std::unordered_set<PycCode *> code_seen;
3477+
34653478
void decompyle(PycRef<PycCode> code, PycModule* mod, std::ostream& pyc_output)
34663479
{
3480+
if (code_seen.find((PycCode *)code) != code_seen.end()) {
3481+
fputs("WARNING: Circular reference detected\n", stderr);
3482+
return;
3483+
}
3484+
code_seen.insert((PycCode *)code);
3485+
34673486
PycRef<ASTNode> source = BuildFromCode(code, mod);
34683487

34693488
PycRef<ASTNodeList> clean = source.cast<ASTNodeList>();
@@ -3557,4 +3576,6 @@ void decompyle(PycRef<PycCode> code, PycModule* mod, std::ostream& pyc_output)
35573576
start_line(cur_indent, pyc_output);
35583577
pyc_output << "# WARNING: Decompyle incomplete\n";
35593578
}
3579+
3580+
code_seen.erase((PycCode *)code);
35603581
}

pycdas.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <string>
55
#include <iostream>
66
#include <fstream>
7+
#include <unordered_set>
78
#include "pyc_module.h"
89
#include "pyc_numeric.h"
910
#include "bytecode.h"
@@ -73,6 +74,8 @@ static void iprintf(std::ostream& pyc_output, int indent, const char* fmt, ...)
7374
va_end(varargs);
7475
}
7576

77+
static std::unordered_set<PycObject *> out_seen;
78+
7679
void output_object(PycRef<PycObject> obj, PycModule* mod, int indent,
7780
unsigned flags, std::ostream& pyc_output)
7881
{
@@ -81,6 +84,12 @@ void output_object(PycRef<PycObject> obj, PycModule* mod, int indent,
8184
return;
8285
}
8386

87+
if (out_seen.find((PycObject *)obj) != out_seen.end()) {
88+
fputs("WARNING: Circular reference detected\n", stderr);
89+
return;
90+
}
91+
out_seen.insert((PycObject *)obj);
92+
8493
switch (obj->type()) {
8594
case PycObject::TYPE_CODE:
8695
case PycObject::TYPE_CODE2:
@@ -246,6 +255,8 @@ void output_object(PycRef<PycObject> obj, PycModule* mod, int indent,
246255
default:
247256
iprintf(pyc_output, indent, "<TYPE: %d>\n", obj->type());
248257
}
258+
259+
out_seen.erase((PycObject *)obj);
249260
}
250261

251262
int main(int argc, char* argv[])

0 commit comments

Comments
 (0)