Skip to content

Instantly share code, notes, and snippets.

@bhanubais
Created April 6, 2017 18:54
Show Gist options
  • Save bhanubais/56a2ae23b36f33e91598fa3fad2e914b to your computer and use it in GitHub Desktop.
Save bhanubais/56a2ae23b36f33e91598fa3fad2e914b to your computer and use it in GitHub Desktop.
C language pointer issue. Why I am getting 20 instead of 7 as a value of *nn in following code?
#include <stdio.h>
int *ptr(int n);
void nothing(int n1);
int main(void) {
int *nn = ptr(7);
nothing(20);
printf("*nn is %d\n", *nn); // why I am getting 20 instead of 7?
}
int *ptr(int n) {
int *p = &n;
printf("p is %d\n", *p);
return p;
}
void nothing(int n1) {
// int n2 = n1;
printf("n1 is %d\n", n1);
}
@Blauelf
Copy link

Blauelf commented Apr 7, 2017

When you call ptr(7), then the current stack pointer and a few other pieces of information like the code position to which to return are stored on the stack, then the parameters and variables like n and p are stored on the stack. Parameter n receives a copy of the 7 you passed to the function.

You now return a pointer to parameter n, jump back to the calling code, and the stack is reset to its previous size. The returned pointer is now pointing to a part of the stack that's not in use, but there's no reason to overwrite its content, so it keeps the 7. That space belongs to the programme, so there's also no segmentation fault.

If you now call printf, the *nn is evaluated to 7, and prints that value.

If you call nothing(20) before printf, its parameter is stored in the same place as the parameter to ptr before, so it overwrites the value. Now, *nn would evaluate to 20.

The nice tool valgrind (actually a collection of tools) will complain in your case, I put the output below the comment.

What can you learn there? Don't store/pass pointers to structures that no longer exist, either because they are defined on a stack and the defining code block has been finished, or have been allocated dynamically and have been freed since then. Many security problems are created that way ("use after free").

~/workspace/freestyle/ $ valgrind ./pointer_issue
==2768== Memcheck, a memory error detector
==2768== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==2768== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==2768== Command: ./pointer_issue
==2768== 
p is 7
n1 is 20
==2768== Conditional jump or move depends on uninitialised value(s)
==2768==    at 0x5E034CE: vfprintf (vfprintf.c:1660)
==2768==    by 0x5E07E70: buffered_vfprintf (vfprintf.c:2356)
==2768==    by 0x5E02DFD: vfprintf (vfprintf.c:1313)
==2768==    by 0x5E0D3D8: printf (printf.c:33)
==2768==    by 0x42D4D8: main (pointer_issue.c:9)
==2768==  Uninitialised value was created by a stack allocation
==2768==    at 0x42D467: main (pointer_issue.c:8)
==2768== 
==2768== Use of uninitialised value of size 8
==2768==    at 0x5E0299B: _itoa_word (_itoa.c:179)
==2768==    by 0x5E06636: vfprintf (vfprintf.c:1660)
==2768==    by 0x5E07E70: buffered_vfprintf (vfprintf.c:2356)
==2768==    by 0x5E02DFD: vfprintf (vfprintf.c:1313)
==2768==    by 0x5E0D3D8: printf (printf.c:33)
==2768==    by 0x42D4D8: main (pointer_issue.c:9)
==2768==  Uninitialised value was created by a stack allocation
==2768==    at 0x42D467: main (pointer_issue.c:8)
==2768== 
==2768== Conditional jump or move depends on uninitialised value(s)
==2768==    at 0x5E029A5: _itoa_word (_itoa.c:179)
==2768==    by 0x5E06636: vfprintf (vfprintf.c:1660)
==2768==    by 0x5E07E70: buffered_vfprintf (vfprintf.c:2356)
==2768==    by 0x5E02DFD: vfprintf (vfprintf.c:1313)
==2768==    by 0x5E0D3D8: printf (printf.c:33)
==2768==    by 0x42D4D8: main (pointer_issue.c:9)
==2768==  Uninitialised value was created by a stack allocation
==2768==    at 0x42D467: main (pointer_issue.c:8)
==2768== 
==2768== Conditional jump or move depends on uninitialised value(s)
==2768==    at 0x5E06682: vfprintf (vfprintf.c:1660)
==2768==    by 0x5E07E70: buffered_vfprintf (vfprintf.c:2356)
==2768==    by 0x5E02DFD: vfprintf (vfprintf.c:1313)
==2768==    by 0x5E0D3D8: printf (printf.c:33)
==2768==    by 0x42D4D8: main (pointer_issue.c:9)
==2768==  Uninitialised value was created by a stack allocation
==2768==    at 0x42D467: main (pointer_issue.c:8)
==2768== 
==2768== Conditional jump or move depends on uninitialised value(s)
==2768==    at 0x5E03599: vfprintf (vfprintf.c:1660)
==2768==    by 0x5E07E70: buffered_vfprintf (vfprintf.c:2356)
==2768==    by 0x5E02DFD: vfprintf (vfprintf.c:1313)
==2768==    by 0x5E0D3D8: printf (printf.c:33)
==2768==    by 0x42D4D8: main (pointer_issue.c:9)
==2768==  Uninitialised value was created by a stack allocation
==2768==    at 0x42D467: main (pointer_issue.c:8)
==2768== 
==2768== Conditional jump or move depends on uninitialised value(s)
==2768==    at 0x5E0361C: vfprintf (vfprintf.c:1660)
==2768==    by 0x5E07E70: buffered_vfprintf (vfprintf.c:2356)
==2768==    by 0x5E02DFD: vfprintf (vfprintf.c:1313)
==2768==    by 0x5E0D3D8: printf (printf.c:33)
==2768==    by 0x42D4D8: main (pointer_issue.c:9)
==2768==  Uninitialised value was created by a stack allocation
==2768==    at 0x42D467: main (pointer_issue.c:8)
==2768== 
*nn is 20
==2768== 
==2768== HEAP SUMMARY:
==2768==     in use at exit: 0 bytes in 0 blocks
==2768==   total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==2768== 
==2768== All heap blocks were freed -- no leaks are possible
==2768== 
==2768== For counts of detected and suppressed errors, rerun with: -v
==2768== ERROR SUMMARY: 8 errors from 6 contexts (suppressed: 0 from 0)

Executive summary: You're reading from address stored in nn with nn pointing to a space that's currently marked as "unused". Could have any value.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment