Open jsmith173 opened 5 months ago
jsmith173 wrote at 2024-3-26 01:36 -0700:
My protection function starts this way, so I'm appended the
results = printed
line to my code and returning withsafe_globals["results"]
at the end of this function.
The safe_globals["results"]
looks strange.
RestrictedPython
's "print" support works as follows:
If a module (outside a function definition)
or function definition uses either print
or printed
for
the first time, code for the assignment
_print = _print_(_getattr_)
is generated.
Usually, this would assign a PrintCollector
to _print
.
Calls to print
are translated into calls to _print._call_print
.
With RestrictedPython
's PrintCollector
, this will
collect the "print"ed output
Accesses to printed
are translated into _print()
.
With RestrictedPython
's PrintCollector
, this will
return the collected output
Thus, if you want to use the collected output, you use
printed
in an expession - e.g. the right hand side of an assignment.
The signature of exec
is (code, [globals, [locals]])
.
If you pass both globals
and locals
, you will find
the result of assignments in locals
, otherwise in globals
.
Thus your use of RestrictedPython
might look like:
code = compile_restricted(...)
gbls = ... create_my_safe_globals ...
exec(code, gbls)
gbls["..."]
or
my_safe_globals = ...
code = compile_restricted(...)
lcls = {}
exec(code, my_safe_globals, lcls)
lcls["..."]
Is this the correct way to collect the print messages? Sometimes I have got error messages like this
"Line 2: SyntaxError: invalid syntax at statement: 'results = printed'" However
results = printed
is not in the original code.
You might have forgotten something (e.g. a closing parenthesis).
I suggest you output the complete code should the compilation raise an exception. You then check this output to understand the exception.
I think I did it previously as you suggests.
I have a function that decides the input is vulnerable or not. This function also should return the printed output (if has). In case of vulnerability it raises an exception. To return the printed output I have added a right hand access to the source code results = printed
. However in some cases the compile or the exec report problem at this line however this line is not the part of the original code. This is a syntax error in the input of course but the problem is that the reported line is the extra added line.
So is there any other way to access the printed output? For example 'PrintCollector.txt'?
jsmith173 wrote at 2024-3-26 02:54 -0700:
I think I did it previously as you suggests. I have a function that decides the input is vulnerable or not. This function also should return the printed output (if has). In case of vulnerability it raises an exception. To return the printed output I have added a right hand access to the source code
results = printed
. However in some cases the compile or the exec report problem at this line however this line is not the part of the original code. This is a syntax error in the input of course but the problem is that the reported line is the extra added line.
Syntax errors are often only recognized after the error point. I have given you an example (missing parethesis in function call). Thus, the syntax error may indicate your added line even though the actual error is in the "original code".
So is there any other way to access the printed output? For example 'PrintCollector.txt'?
Sure. But, it is unlikely to solve your problem (which likely is a syntax error in the "original code"). The syntax error will not disapear when you do not add your assignment.
In my previous comment, I detailed how RestrictedPython
implements the print functionality.
If you reread it, you will find that via an appropriate definition of _print
you can control (almost) everything.
One possibility would be to let the _print
call return a
PrintCollector
instance preinstantiated for an exec
.
Something like:
code = compile_restricted(...)
...
my_collector = PrintCollector()
gbls = get_safe_globals().copy()
gbls["_print"] = lambda *args: my_collector
lcls = {}
exec(code, gbls, lcls)
printed = my_collector()
My protection function starts this way, so I'm appended the
results = printed
line to my code and returning withsafe_globals["results"]
at the end of this function. Is this the correct way to collect the print messages? Sometimes I have got error messages like this"Line 2: SyntaxError: invalid syntax at statement: 'results = printed'" However
results = printed
is not in the original code.For the follwing input for example
@__builtins__