I have this code that have no idea why it works in online compiler (https://www.programiz.com/c-programming/online-compiler/) (copy this code below and run in that online compiler to verify it).
#include <stdio.h>
void foo(){
static int locl = 0;
locl ;
printf("accessing locl from INSIDE scope: %i\n", locl);
}
int main() {
for (int i=0; i<3; i ){
foo();
printf("accessing locl from OUTSIDE scope: %i\n",*((int *)((unsigned long long)(&foo) 11979)));
}
return 0;
}
OUTPUT:
accessing locl from INSIDE scope: 1
accessing locl from OUTSIDE scope: 1
accessing locl from INSIDE scope: 2
accessing locl from OUTSIDE scope: 2
accessing locl from INSIDE scope: 3
accessing locl from OUTSIDE scope: 3
So the output is what I expect.
Variable with name locl
is static integer that will increment 1 every time foo
is called, but focus on this part when I tried accessing static local variable outside its scope:
*((int *)((unsigned long long)(&foo) 11979))
Where the constant 11979
is comefrom?
Is that constant is universal when applying convert static local variable to global
in another platform?
Is there guarantee that part code is always success executed during runtime?
If not, is there a way UNIVERSALLY to convert static local variable to global aka accessing static local variable from outside its scope?
CodePudding user response:
Writing code like that is a crime against nature. Exposing unprepared students to it is a crime against humanity.
Its author figured out that specific code with that specific compiler and that specific linker (including which versions of them), building with the specific options that that online compiler is using, the locl
object was stored 11,979 bytes away from where the code for the foo
function was stored. The code (int *)((unsigned long long)(&foo) 11979)
converts the address of &foo
to an integer type, adds 11,979 to it, and converts it to a pointer to an int
.
This code may break if other variables are added, if other functions are added, if various other modifications to the source code are made, if the target system of the build is changed, if the compiler is changed, and so on. There is essentially nothing that guarantees code like this will work except that if you change absolutely nothing about it, it may behave the same as it did before, like avoiding any vibration or air movement near a coin balanced on its edge might guarantee the coin does not fall over.
It does demonstrate that inside a process, the memory assigned to that process is generally visible and can be manipulated in devious ways, which is something programmers should know because malicious people can take advantage of it.
CodePudding user response:
Where the constant 11979 is comefrom? Is that constant is universal when applying convert static local variable to global in another platform?
I have absolutely no idea what the magic number does :(
Is there guarantee that part code is always success executed during runtime?
No, it shows a different result in godbolt with gcc 12.1
if not, is there a way UNIVERSALLY to convert static local variable to global aka accessing static local variable from outside its scope?
Yes, there is, returning a pointer to the static
variable:
#include <stdio.h>
int *foo(void)
{
static int x = 0;
return &x;
}
int main(void)
{
*foo() = 42;
printf("%d\n", *foo());
return 0;
}
Output:
42