Adobe Interview Question
Software Engineer / DevelopersCountry: India
Interview Type: In-Person
in 64bit os, compiled with gcc;
int fun()
{
/*write code here.*/
int p[0];
p[8] = 20;
}
int main()
{
int i=10;
fun();
printf("%d",i);
}
Its about memory layout of functions and variable.
if you disassemble the excutable you will find this
(gdb) disas fun
Dump of assembler code for function fun:
0x000000000040052d <+0>: push %rbp
0x000000000040052e <+1>: mov %rsp,%rbp
0x0000000000400531 <+4>: movl $0x14,0x1c(%rbp)
0x0000000000400538 <+11>: pop %rbp
0x0000000000400539 <+12>: retq
End of assembler dump.
(gdb) disas main
Dump of assembler code for function main:
0x000000000040053a <+0>: push %rbp
0x000000000040053b <+1>: mov %rsp,%rbp
0x000000000040053e <+4>: sub $0x10,%rsp
0x0000000000400542 <+8>: movl $0xa,-0x4(%rbp)
0x0000000000400549 <+15>: mov $0x0,%eax
0x000000000040054e <+20>: callq 0x40052d <fun>
0x0000000000400553 <+25>: mov -0x4(%rbp),%eax
0x0000000000400556 <+28>: mov %eax,%esi
0x0000000000400558 <+30>: mov $0x4005f4,%edi
0x000000000040055d <+35>: mov $0x0,%eax
0x0000000000400562 <+40>: callq 0x400410 <printf@plt>
0x0000000000400567 <+45>: leaveq
0x0000000000400568 <+46>: retq
End of assembler dump.
in memory layout, function fun resides before main. So, you can access main function's internal variable via pointer arithmetic.
Now, all you have to find is relative location for i from the place you are assigning the value.
It's a local, the scope of which is the function - main. Compilers put it on the stack, the stack grows down.
Declare a local in fun(), mine's called 'i'. The address of fun():i is on the stack. There are only pointers above it: stack and code pointers. We can use this to say anything on the stack which has the value '10' is our initialised integer from main. We then write '20' to that address.
{{
#include <stdio.h>
int fun()
{
/* Wander up the stack in integer pointers look for the number 10 & change it to 20.*/
int i;
int *p=&i;
int j;
for(j=0;*(p+j)!=10;j++){
;
}
/* Stack Frame size is j int pointers. */
*(p+j)=20;
}
}}
very very thankz for your code but plese tell me how u do that ??
i can't understand what you have done ?
how you reached main::i ??
please explain how ????
I think motivation of this question has come from reading phrack magazine.
Shaun answer is right however there is assumption there that stack will go downwards and memory allocation will go upwards.
I did something functionally equivalent, and as expected, it works only with all optimizations disabled. If you turn on typical release build optimizations, all bets are off! For example, my compiler (VS2013) with maximize speed turned on, optimizes away the existence of main::i altogether. It inlines fun() ahead of the call to printf(), and then pushes the value 10 directly onto the stack *after* calling fun(), just before calling printf. There is no way to know at compile time that main::i is being accessed from fun(), so this is obviously a very unsafe way to code (which your interviewer probably expected you to point out).
Secondly, even without optimizations, I don't think you can guarantee this technique to work 100% of the time. What if, while walking the stack, an int-sized chunk of something else happens to evaluate to 10 when interpreted as an int?
1. pass i as a pointer to the function and update the value of i.
2. Since I is a local to main and is initializedd, it will be held in the bss segment of the user program. Inside the function fun which will be put onto stack, if we have access to the bss segment by manipulating the address and updating the value at that address.
Niyati, where are you struggling. There's text, data & stack segments... C pointers are actual addresses ... The difficult bit is stacks;
Google wikipedia computer hardware stack Select the first answer and check #Hardware_stacks
If you have a pointer to 'somewhere' on the stack you can look at the adjacent locations until you find the variable main::i.
This answer is about C pointer arithmetic and memory layout. Extra points could be earned for the mechanisms used to obfuscate stack addresses, write protecting memory etc.
Horrible question. There is no way to do this in pure C in a reliable way. The stack may grow in either direction, depending on the architecture. The compiler may decide to keep i in a register when assigned 10 in the main, so any change to memory done in fun() would have no effect on the result of the printf.
I agree. There is no portable safe way to access main::i from fun() and you can easily create infinite loops or corrupt the stack trying the search and replace trick.
I would give the interviewee half the credit for thinking of trying to walk back the stack, and the other half for coming up with the conclusion that this is unsafe and providing at least 2 ways it could fail. There are multiple failure cases from compiler optimizations alone (main::i not allocated on the stack, or not at all, functions re-ordered due to no compiler-detectable dependencies, etc.), the issue of non-uniqueness of the searched-for value on the stack, hardware implementation issues that make code non-portable. On some systems you could subtract pointers to sequentially-declared local variables and dynamically detect which way the stack grows, slightly increasing your portability success rate, but event this is something the compiler is free to thwart, particularly with optimizations turned on.
How about:
int fun()
{
int i = 5;
printf("%d", i);
exit(EXIT_SUCCESS);
}
int _tmain(int argc, _TCHAR* argv[])
{
int i = 5;
fun();
printf("%d", i);
return 0;
}
int fun(&temp)
{
temp=20; /*write code here.*/
}
int main()
{
int i=10;
fun(i);
printf("%d",i);
}
}
- Chris November 03, 2014