Found this on /prog/. I actually GDB'd it, and yes, it was truly a recursion. But how did it happen?
// This works on 32-bit x86 Linux with gcc as long as you don't enable optimization.
#include <stdio.h>
#include <stdlib.h>
static void factorial(int in, int *out)
{
*(&in-1)-=5-5*(1/in);
*out*=in--;
}
int main(int argc, char **argv)
{
int result=1;
int number=0;
if (argc!=2)
exit(1);
number=atoi(argv[1]);
if (number<1)
exit(2);
factorial(number, &result);
printf("%d! = %d\n", number, result);
return 0;
}
$ ./factorial 3
3! = 6
$ ./factorial 5
5! = 120
Recursion is when a function calls itself until someone stops it. If no one stops it then it'll recurse (call itself) forever. Recursive functions let you perform a unit of work multiple times.
To avoid recursive triggers you can create a class with a static Boolean variable with default value true. In the trigger, before executing your code keep a check that the variable is true or not. Once you check make the variable false.
A recursive call is one where procedure A calls itself or calls procedure B which then calls procedure A again. Each recursive call causes a new invocation of the procedure to be placed on the call stack.
Many professional developers probably already know how to replace recursive functions to avoid stack-overflow problems in advance by replacing with iterative function or using stack (heap stack) and while-loop (recursive simulation function).
Sweet. ;)
This is extremely non-portable code that works only on x86. What it's doing is changing the return address on the stack so that if in>1
, the function returns not to the instruction following the call
instruction, but to the call instruction itself. A call instruction on x86 is five bytes (one opcode plus the 4-byte address of the call destination), so five needs to be subtracted from the return address.
This
*(&in-1)-=5-5*(1/in);
is just an obfuscated way of saying
if(in>1)
*(&in-1)-=5;
And &in-1
is where the return address lives on the stack.
It's corrupting return addresses on the stack to cause the recursion to happen.
*(&in-1)-=5-5*(1/in);
&in-1
is probably the pushed return address. the rest is just unpleasant magic.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With