5 ms·
This leverages Perl's BEGIN block which runs before the main part of the code. I suppose the same fun could be had in other languages: if day_of_week is "F
by athenot 5y ago
This leverages Perl's BEGIN block which runs before the main part of the code. I suppose the same fun could be had in other languages:
if day_of_week is "Friday"
eval(piece_of_incorrect_code)
else
do_sane_operation
- yodon 5y agoMoral quandary of the morning: Do I point out the sign error or do I just say please don't merge this?
- saba2008 5y agoMost other languages would require `eval` and having incorrect code as syntactically correct string literal. But because Perl is parsed as it is executed, incorrect code raises syntax error only when it is reached by execution.
- cestith 5y agoPerl is not parsed as it is executed. It is compiled to opcodes then run. The BEGIN block, however, explicitly runs code at compile time. It is literally compiling different code on different days, then attempting to run it.
- RandalSchwartz 5y agoTechnically not opcodes, but internal Data Structures. A serializer was written for that, to permit ".pmc files".
- cestith 5y agoOh, hey, Randal. Thanks for the correction. Looking forward to the next time we can have steaks and Scotch.
- JohnDeHope 5y agoRight, the beauty of this is that it's a syntax error he's produced. Sure any language can write code to produce a runtime error under any condition at all. And a lot of languages have features that allow them to run code at compile time, and similarly produce errors then too. But those languages don't allow you to ruin the syntax of the language. I guess it's something that requires macros. Would it be safe to say that any language with macros can do this? Or is there something even more interesting with perl going on here?
- im3w1l 5y agoBash parses as it runs so something as simple as this works if [ $(date +%u) -ne 5 ] then exit fi (
- lloeki 5y agoBash even reads the file as it goes, so if you run a "long-running" script (a sleep is enough), edit far enough down, and write the file again, the previously started bash will end up running the new content once it gets up to reading where the change happened.
- saba2008 5y agoYou can exploit it do distinguish whenever script is `curl | bash`'ed. Add `sleep 1`, and detect pause on server. Then, if pause detected - serve attack payload. If not - somebody is careful enough to download and audit, so serve just the script.
- jwilk 5y agohttps://www.idontplaydarts.com/2016/04/detecting-curl-pipe-bash-server-side/ https://www.idontplaydarts.com/2016/04/detecting-curl-pipe-b... Discussed on HN: 2020: https://news.ycombinator.com/item?id=25356757 https://news.ycombinator.com/item?id=25356757 (133 comments) 2018: https://news.ycombinator.com/item?id=17636032 https://news.ycombinator.com/item?id=17636032 (146 comments) 2016: https://news.ycombinator.com/item?id=11532599 https://news.ycombinator.com/item?id=11532599 (122 comments)
- tyingq 5y ago>incorrect code raises syntax error only when it is reached by execution. That's not generally true for Perl. The BEGIN block is used to get in that state here. "Some incorrect code raises syntax error only when it is reached" is true. It's generating this on Fridays: &f() / 1; And this on other days: f(/1;#/+); If you run the same code, but without BEGIN blocking the assignment to *f, it isn't incorrect code. It evaluates as: 'f' / 1;
- ars 5y agoWhat happens if you run this code in a loop Thursday night just before Friday? Does the parse that happens on Thursday take precedence or is it reparsed every single time through the loop?
- tyingq 5y agoThe BEGIN block only runs once. That is: while (1) { BEGIN {print "hello\n"} sleep 1; } Will only print "hello" one time. You could loop inside the BEGIN block and then drop out of the loop at some point. If you dropped out on friday, after the code assigning *f, it would run correctly. So: BEGIN { sleep 86400; *f = (localtime->wdayname eq 'Fri') ? sub() {} : sub {}; } f/1;#/+ Would run correctly if you started it on Thursday.
- petercooper 5y agoRuby has that latter quality in many scenarios. For example: p 'Friday!' if Time.now.wday==5 || h
- btilly 5y agoBut because Perl is parsed as it is executed, incorrect code raises syntax error only when it is reached by execution. Sorry, but you're dead wrong. Perl is not parsed as it is executed, which can be verified easily by writing a program with a syntax error at the end, and seeing that it doesn't run code at the top. Try it with the following program. print "Hello, world\n"; This line raises a syntax error before the previous line tries to execute. What is going on is that BEGIN blocks are special, they are executed as soon as they are parsed. With them we can interleave parsing and execution. In this case we're assigning to a symbol. And then the parsing of the final line is dependent on whether or not that symbol has a prototype. See https://perldoc.perl.org/perlsub#Prototypes https://perldoc.perl.org/perlsub#Prototypes for what Perl prototypes are, and to see why they would affect parsing.
- runeks 5y agoThat looks like a syntactically correct piece of code that fails at runtime.