I just had an exam in my class today --- reading C code and input, and the required answer was what will appear on the screen if the program actually runs. One of the questions declared a[4][4] as a global variable and at a point of that program, it tries to access a[27][27], so I answered something like "Accessing an array outside its bounds is an undefined behavior" but the teacher said that a[27][27] will have a value of 0.
Afterwards, I tried some code to check whether "all uninitialized golbal variable is set to 0" is true or not. Well, it seems to be true.
So now my question:
Seems like some extra memory had been cleared and reserved for the code to run. How much memory is reserved? Why does a compiler reserve more memory than it should, and what is it for?
Will a[27][27] be 0 for all environment?
Edit :
In that code, a[4][4] is the only global variable declared and there are some more local ones in main().
I tried that code again in DevC++. All of them is 0. But that is not true in VSE, in which most value are 0 but some have a random value as Vyktor has pointed out.
You were right: it is undefined behavior and you cannot count it always producing 0.
As for why you are seeing zero in this case: modern operating systems allocate memory to processes in relatively coarse-grained chunks called pages that are much larger than individual variables (at least 4KB on x86). When you have a single global variable, it will be located somewhere on a page. Assuming a is of type int[][] and ints are four bytes on your system, a[27][27] will be located about 500 bytes from the beginning of a. So as long as a is near the beginning of the page, accessing a[27][27] will be backed by actual memory and reading it won't cause a page fault / access violation.
Of course, you cannot count on this. If, for example, a is preceded by nearly 4KB of other global variables then a[27][27] will not be backed by memory and your process will crash when you try to read it.
Even if the process does not crash, you cannot count on getting the value 0. If you have a very simple program on a modern multi-user operating system that does nothing but allocate this variable and print that value, you probably will see 0. Operating systems set memory contents to some benign value (usually all zeros) when handing over memory to a process so that sensitive data from one process or user cannot leak to another.
However, there is no general guarantee that arbitrary memory you read will be zero. You could run your program on a platform where memory isn't initialized on allocation, and you would see whatever value happened to be there from its last use.
Also, if a is followed by enough other global variables that are initialized to non-zero values then accessing a[27][27] would show you whatever value happens to be there.
Accessing an array out of bounds is undefined behavior, which means the results are unpredictable so this result of a[27][27] being 0 is not reliable at all.
clang tell you this very clearly if we use -fsanitize=undefined:
runtime error: index 27 out of bounds for type 'int [4][4]'
Once you have undefined behavior the compiler can really do anything at all, we have even seen examples where gcc has turned a finite loop into an infinite loop based on optimizations around undefined behavior. Both clang and gcc in some circumstances can generate and undefined instruction opcode if it detects undefined behavior.
Why is it undefined behavior, Why is out-of-bounds pointer arithmetic undefined behaviour? provides a good summary of reasons. For example, the resulting pointer may not be a valid address, the pointer could now point outside the assigned memory pages, you could be working with memory mapped hardware instead of RAM etc...
Most likely the segment where static variables are being stored is much larger then the array you are allocating or the segment that you are stomping though just happens to be zeroed out and so you are just lucky in this case but again completely unreliable behavior. Most likely your page size is 4k and access of a[27][27] is within that bound which is probably why you are not seeing a segmentation fault.
What the standard says
The draft C99 standard tell us this is undefined behavior in section 6.5.6 Additive operators which covers pointer arithmetic which is what an array access comes down to. It says:
When an expression that has integer type is added to or subtracted
from a pointer, the result has the type of the pointer operand. If the
pointer operand points to an element of an array object, and the array
is large enough, the result points to an element offset from the
original element such that the difference of the subscripts of the
resulting and original array elements equals the integer expression.
[...]
If both the pointer operand and the result point to elements of the
same array object, or one past the last element of the array object,
the evaluation shall not produce an overflow; otherwise, the behavior
is undefined. If the result points one past the last element of the
array object, it shall not be used as the operand of a unary *
operator that is evaluated.
and the standards definition of undefined behavior tells us that the standard imposes no requirements on the behavior and notes possible behavior is unpredictable:
behavior, upon use of a nonportable or erroneous program construct or
of erroneous data, for which this International Standard imposes no
requirements
NOTE Possible undefined behavior ranges from ignoring the situation
completely with unpredictable results, [...]
Here is the quote from the standard, that specifies what is undefined behavior.
J.2 Undefined behavor
An array subscript is out of range, even if an object is apparently accessible with the
given subscript (as in the lvalue expression a[1][7] given the declaration int
a[4][5]) (6.5.6).
Addition or subtraction of a pointer into, or just beyond, an array object and an
integer type produces a result that points just beyond the array object and is used as
the operand of a unary * operator that is evaluated (6.5.6).
In your case you the array subscript is completely outside of the array. Depending that the value will be zero is completely unreliable.
Furthermore the behavior of entire program is in question.
If just run your code from visual studio 2012 and got result like this (different at each run):
Address of a: 00FB8130
Address of a[4][4]: 00FB8180
Address of a[27][27]: 00FB834C
Value of a[27][27]: 0
Address of a[1000][1000]: 00FBCF50
Value of a[1000][1000]: <<< Unhandled exception at 0x00FB3D8F in GlobalArray.exe:
0xC0000005: Access violation reading location 0x00FBCF50.
When you look at Modules window you see that your application module memory range is 00FA0000-00FBC000. And unless you have CRT Checks turned on nothing will control what do you do inside your memory (as long as you don't violate memory protection).
So you got 0 at a[27][27] purely by chance. When you open memory view from position 00FB8130 (a) you will probably see something like this:
0x00FB8130 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x00FB8140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x00FB8150 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x00FB8160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x00FB8170 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x00FB8180 01 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 ................
0x00FB8190 c0 90 45 00 b0 e9 45 00 00 00 00 00 00 00 00 00 À.E.°éE.........
0x00FB81A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x00FB81B0 00 00 00 00 80 5c af 0f 00 00 00 00 00 00 00 00 ....€\¯.........
0x00FB81C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
..........
0x00FB8330 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x00FB8340 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ <<<<
0x00FB8350 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
.......... ^^ ^^ ^^ ^^
It's possible that with your compiler you will always get 0 for that code because of how it uses memory, but just few bytes away you can find another variable.
For example with memory shown above a[6][0] points to address 0x00FB8190 which contains integer value of 4559040.
Then get your teacher to explain this one.
I don't know if this will work on your system but playing about with blatting memory AFTER the array a with non-zero'd bytes gives a different result for a[27][27].
On my system, when I printed contents of a[27][27] it was 0xFFFFFFFF. ie -1 converted to unsigned is all bits set in twos complement.
#include <stdio.h>
#include <string.h>
#define printer(expr) { printf(#expr" = %u\n", expr); }
unsigned int d[8096];
int a[4][4]; /* assuming an int is 4 bytes, next 4 x 4 x 4 bytes will be initialised to zero */
unsigned int b[8096];
unsigned int c[8096];
int main() {
/* make sure next bytes do not contain zero'd bytes */
memset(b, -1, 8096*4);
memset(c, -1, 8096*4);
memset(d, -1, 8096*4);
/* lets check normal access */
printer(a[0][0]);
printer(a[3][3]);
/* Now we disrepect the machine - undefined behaviour shall result */
printer(a[27][27]);
return 0;
}
This is my output:
a[0][0] = 0
a[3][3] = 0
a[27][27] = 4294967295
I saw in comments about viewing memory in Visual Studio. Easiest way is to add a break-point somewhere in your code (to halt execution) then go into Debug... windows... Memory menu, select eg Memory 1. You then find the memory address of your array a. In my case address was 0x0130EFC0. so you enter 0x0130EFC0 in the address fiend and press Enter. This shows the memory at that location.
Eg in my case.
0x0130EFC0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ..................................
0x0130EFE2 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff ff ff ff ..............................ÿÿÿÿ
0x0130F004 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
0x0130F026 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
0x0130F048 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
The zeros are of the course the array a, which has a byte size of 4 x 4 x sizeof an int (4 in my case) = 64 bytes. The bytes from address 0x0130EFC0 are 0xFF each (from b,c, or d contents).
Note that:
0x130EFC0 + 64 = 0x130EFC0 + 0x40 = 130F000
which is that the start of all those ff bytes you see. Probably array b.
For common compilers, accessing an array beyond its bounds can give predictable results only in very special cases, and you should not rely on that. Example :
int a[4][4];
int b[4][4];
Provided there are no alignment problem, and you ask neither aggressive optimisation nor sanitization checks, a[6][1] should in reality be b[2][1]. But please never do that in production code !
On a particular system, your teacher may be correct -- that may be how your particular compiler and operating system would behave.
On a generic system (i.e. without "insider" knowledge) then your answer is correct: this is UB.
First of all C language have not boundary check. In effect it have no check at all on almost everything. This is the joy and the doom of C.
Now going back to the issue, if you overflow the memory doesn't mean that you trigger a segfault.
Lets have a closer look to how it works.
When you start a program, or enter a subroutine the processor saves on the stack the address to which return when function ends.
The stack has been initialized from OS during process memory allocation, and got a range of legal memory where you can read or write as you like, not only store return addresses.
The common practice used by compilers to create local (automatic) variables is to reserve some space on the stack, and use that space for variables. Look following well known 32 bits assembler sequence, named prologue, that you'll find on any function enter:
push ebp ;save register on the stack
mov ebp,esp ;get actual stack address
sub esp,4 ;displace the stack of 4 bytes that will be used to store a 4 chars array
considering that stack grows in the reverse direction of data, the layout of memory is:
0x0.....1C [Parameters (if any)] ;former function
0x0.....18 [Return Address]
0x0.....14 EBP
0x0.....10 0x0......x ;Local DWORD parameter
0x0.....0C [Parameters (if any)] ;our function
0x0.....08 [Return Address]
0x0.....04 EBP
0x0.....00 0, 'c', 'b', 'a' ;our string of 3 chars plus final nul
This is known as stack frame.
Now consider the string of four bytes starting at 0x0....0 and ending at 0x....3. If we write more than 3 chars in the array we will go replacing sequentially: the saved copy of EBP, the return address, parameters, local variables of previous function then its EBP, return address, etc.
The most scenographic effect we get is that, on function return, the CPU try to jump back to a wrong address generating a segfault. Same behaviour can be achieved if one of local variables are pointers, in this case we will try to read, or write, to wrong locations triggering again the segfault.
When segfault could not happen:
when the bloated variable is not on the stack, or you have so many local variables that you overwrite them without touching the return address (and they are not pointers).
Another case is that the processor reserves a guard space between local variables and return address, in this case the buffer overflow doesn't reach the address.
Another possibility is accessing array elements randomly, in this case an oversized array can exceed stack space and overflow on other data, but luckily we mdon't touch those elements that are mapped where is saved the return address (everythibng can happen...).
When we can have segfault bloating variables that are not on stack?
When overflowing array bound or pointers.
I hope these are useful info...
Related
int main (void){
int num1=2;
int *pnum=NULL;
pnum=&num1;
*pnum++;
printf("%d",*pnum);
}
why does this code print the address, not the value? Doesn't * dereference the pnum?
Check the precedence of operators: postfix unary operators bind tighter than prefix unary operators, so *pnum++ is equivalent to *(pnum++), not to (*pnum)++.
pnum++ increments the pointer pnum and returns the old value of pnum. Incrementing a pointer makes it point to the next element of an array. Any variable can be treated as an array of one element, so pnum points to the element after the first in the one-element array located where num1 is, which I'll call num1_array[1]. It is valid for a pointer to point to the end of an array, i.e. one position past the last element. It is not valid to dereference that pointer: that would be an array overflow. But it is valid to calculate the pointer. Constructing an invalid pointer in C is undefined behavior, even if you don't dereference it; however this pointer is valid.
*pnum++ dereferences the old value of pnum. Since that was a pointer to num1, this expression is perfectly valid and its value is the value of num1. At this point, any halfway decent compiler would warn that the value is unused. If you didn't see this message, configure your compiler to print more warnings: unfortunately, many compilers default to accepting bad code rather than signal the badness. For example, with GCC or Clang:
$ gcc -Wall -Wextra -Werror a.c
a.c: In function ‘main’:
a.c:6:5: error: value computed is not used [-Werror=unused-value]
6 | *pnum++;
| ^~~~~~~
cc1: all warnings being treated as errors
The call to printf receives the argument *pnum. We saw before that at this point, pnum points to the end of the one-element array num1_array[1]. This pointer is valid, but since it points to the end of an object, dereferencing has undefined behavior. In practice, this usually either crashes or prints some garbage value that happens to be in a particular memory location. When you're debugging a program, there are tools that can help by making it more likely that an invalid pointer will cause a crash rather than silently using a garbage value. For example, with GCC or Clang, you can use AddressSanitizer:
$ export ASAN_OPTIONS=symbolize=1
$ gcc -Wall -Wextra -fsanitize=address a.c && ./a.out
a.c: In function ‘main’:
a.c:6:5: warning: value computed is not used [-Wunused-value]
6 | *pnum++;
| ^~~~~~~
=================================================================
==2498121==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fff15ae3e74 at pc 0x55d593978366 bp 0x7fff15ae3e30 sp 0x7fff15ae3e20
READ of size 4 at 0x7fff15ae3e74 thread T0
#0 0x55d593978365 in main (/tmp/stackoverflow/a.out+0x1365)
#1 0x7f525a1380b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
#2 0x55d59397818d in _start (/tmp/stackoverflow/a.out+0x118d)
Address 0x7fff15ae3e74 is located in stack of thread T0 at offset 36 in frame
#0 0x55d593978258 in main (/tmp/stackoverflow/a.out+0x1258)
This frame has 1 object(s):
[32, 36) 'num1' (line 3) <== Memory access at offset 36 overflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
(longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow (/tmp/stackoverflow/a.out+0x1365) in main
Shadow bytes around the buggy address:
0x100062b54770: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100062b54780: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100062b54790: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100062b547a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100062b547b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x100062b547c0: 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1[04]f3
0x100062b547d0: f3 f3 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100062b547e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100062b547f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100062b54800: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100062b54810: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==2498121==ABORTING
This trace tells you:
That there was a buffer overflow in a local variable (stack-buffer-overflow).
That the overflowing access was an attempt to read 4 bytes (READ of size 4).
Some more information about the problematic address ([32, 36) 'num1'). You can see that the program tried to access memory just after num1.
The address of the problematic instruction (#0 0x55d593978365). You can set a breakpoint there in a debugger to examine what the program might be doing.
On most platforms, given your program, num1 is a variable on the stack, and the end of num1 is the address of the previous variable on the stack. This could be anything, depending on the details of how your compiler accesses memory. One of the many things this could be is pnum, if pnum and num1 happen to have the same size on your platform (this is typically the case on 32-bit platforms) and the compiler decides to put pnum just before num1 on the stack (this depends heavily on the compiler, the optimization level, and fine details of the program). So it is plausible for your program to print the address of pnum: not because *pnum somehow didn't invoke the dereference operator, but because your program has made pnum point to itself.
Postfix operators always have higher precedence than prefix operators in C. So *pnum++ is equivalent to *(pnum++) -- it increments the pointer, not the value pointed at.
You need (*pnum)++ or ++*pnum if you want to increment the pointed at value.
You need to put parenthesis around *pnum. Otherwise the address which the pointer points to is changed. pnum++ is pointer arithmetic and increments the pointer by the number equal to the size of the data type for which it is a pointer, in this case sizeof(int). This means it doesn't point to the correct value anymore and the program therefore prints “garbage” as mentioned by Eugene Sh. in the comments, because it dereferences the incremented pointer using *(pnum++).
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int num1 = 2;
int *pnum = &num1;
(*pnum)++; /* important */
printf("%d\n", *pnum);
return EXIT_SUCCESS;
}
When you write *pnum++; There, you change the address pnum is pointing. And incrementing it by one, we don't really know where it has started to point. As suggested above, it's referencing garbage right now.
I wrote this C code to solve Advent of Code 13 2020. I know, it's probably not viable trying to solve it via brute force, but the program gives the correct answer for the example input.
If I try to let gcc optimize the code, it gives the correct result with -O1, but creates an endless loop with -O2. After all the research my conclusion is that there is undefined behavior in my code, I guess it has to do with the probability that "found" may never be higher than 0 and so "time" would overflow.
Here is the question: Does anybody know how to patch that undefined behavior?
"-Wall -Wextra -pedantic" don't even issue a warning or something.
I just can't find a solution. If I, for example, change the head of the while loop to (!found && time < 10000000000), so that no overflow can occur, it just breaks the loop right away with a time value of 10000000003 when compiled with -O2, but still gives the right result with -O1.
Here is the code, the correct result would be "1068781":
#include <stdio.h>
int main()
{
unsigned int busses[] = {7, 0, 13, 2, 59, 1, 31, 0, 19};
unsigned int busses_used = 9;
unsigned int i = 0;
unsigned int found = 0;
unsigned long long time = 0;
unsigned int offset = 0;
unsigned int increment = 7;
while (!found) {
time += increment;
offset = 0;
for (i = 0; i < busses_used; i++) {
if ((time + offset) % busses[i] == 0) {
found = 1;
offset++;
} else {
found = 0;
break;
}
offset += busses[++i];
}
}
printf("Endtime: %lld\n", time);
return 0;
}
Edit: Thanks to KamilCuk for pointing out that the code is accessing the array out of bounds and teaching how to find out that it is doing so. The problem is solved by adding another 0 at the end of the "busses" array and therefore also setting "busses_used" to 10 instead of 9.
I do not understand the code and not indent to, but the loop is strange. Anyway:
"-Wall -Wextra -pedantic" don't even issue a warning or something.
And there are also other ways to detect UB! Compiling your code with some more -fsanitize=* options results with:
+ gcc -Wall -Wextra -ggdb3 -fsanitize=address -fsanitize=undefined -fsanitize=pointer-compare -fsanitize=pointer-subtract -fsanitize-address-use-after-scope /tmp/1.c
/tmp/1.c:22:29: runtime error: index 9 out of bounds for type 'unsigned int [9]'
/tmp/1.c:22:29: runtime error: load of address 0x7ffc48c7a894 with insufficient space for an object of type 'unsigned int'
0x7ffc48c7a894: note: pointer points here
13 00 00 00 60 60 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 08 aa c7 48 fc 7f 00 00
^
=================================================================
==73835==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffc48c7a894 at pc 0x55c28a5bf773 bp 0x7ffc48c7a800 sp 0x7ffc48c7a7f0
READ of size 4 at 0x7ffc48c7a894 thread T0
#0 0x55c28a5bf772 in main /tmp/1.c:22
#1 0x7f0060bd1151 in __libc_start_main (/usr/lib/libc.so.6+0x28151)
#2 0x55c28a5bf12d in _start (/tmp/tmp.qv8ZsZofOJ.out+0x112d)
Address 0x7ffc48c7a894 is located in stack of thread T0 at offset 84 in frame
#0 0x55c28a5bf208 in main /tmp/1.c:3
This frame has 1 object(s):
[48, 84) 'busses' (line 4) <== Memory access at offset 84 overflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
(longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow /tmp/1.c:22 in main
Shadow bytes around the buggy address:
0x1000091874c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000091874d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000091874e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000091874f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100009187500: 00 00 00 00 00 00 00 00 f1 f1 f1 f1 f1 f1 00 00
=>0x100009187510: 00 00[04]f3 f3 f3 f3 f3 00 00 00 00 00 00 00 00
0x100009187520: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100009187530: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100009187540: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100009187550: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100009187560: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==73835==ABORTING
After quick inspection the out of bounds access to busses happens here:
offset += busses[++i];
Does anybody know how to patch that undefined behavior?
No idea, but write an algorithm that doesn't access the array out of bounds.
I'm not very familiar with C, but I have an app I'm trying to convert over to Node (JS).
I think char may be relatable to Nodes new Buffer() but I'm not 100% certain on this. Any information would be great thanks.
I have this bit of code here:
char data[80];
unsigned long long flag=0;
mysql_real_escape_string(&mysql,data,(char*)&flag,sizeof(flag));
Which mysql_real_escape_string should just copy the data from (char*)&flag) into data.
I'm wondering if I could do this like
var flag = 123;
var buf = new Buffer(80)
buf.writeUInt32LE(flag);
if I console.log(buf); I get
buf.toString();
'\u0000\u0000\u0001\u0000\u0000\u0000\u0000\u0000��p\u0001\u0001\u0000\u0000\u0000P��\u0001\u0001\u0000\u0000\u0000\n\u0000\u0000\u0000\u0000\u0000\u0000\u0000x��\u0001\u0001\u0000\u0000\u0000\u0005\u0000\u0000\u0000\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000#��_�\u0000\u0000\u0001\u0000\u0000\u0000\u0001\u0000\u0000\u0000'
if I printf("%s", data); I get
\0#\0\0\0\0\0
Any information would be great thanks.
Well, I'm not sure why you are allocating such a large buffer for such a small bit of data, but creating a Buffer in Node does not initialize the underlying memory. Therefore, apart from the first 4 bytes overwritten by writeUInt32LE the rest will be gibberish. You should use fill to get consistent output.
var flag = 123;
var buf = new Buffer(80)
buf.fill(0);
buf.writeUInt32LE(flag);
When I add console.log(buf), I get a much more predictable output:
<Buffer 7b 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ... >
I can't can't compare your output from the C snippet, as it seems your input values don't match. Based on your description, I think this will correct your output.
Through the IDA disassembler I've reached this address:
0010FD74 00 00 00 00 00 00 03 00 00 00 00 00 82 03 80 02
Now I need, given the address to get particular bytes; for example the 7th position where there is "03".
I've tried using C language to do this:
char *dummycharacter;
*dummycharacter = *(char*)0x10FD74;
Now if I try to access 7th value with this:
dummycharacter[6]
I don't get 0x03…where am I going wrong?
You're trying to assign the value dummycharacter points to (which is pretty much nowhere, since it's not initialized). Try dummycharacter = (char*)0x10FD74;.
i am studying C now, and I am parsing a raw registry file and read it.
i have some problem now,
000011E0 00 00 00 00 60 01 00 00 B9 01 00 00 00 00 00 00
000011F0 20 C0 26 00 FF FF FF FF 00 00 00 00 FF FF FF FF
00001200 10 FC 00 00 FF FF FF FF 4C 00 01 00 00 00 00 00
this is hex value of REGISTRY file.
fseek(fp,0x11F0,SEEK_SET);
char tmp[4];
int now = ftell(fp);
for(int i = 0 ; i < 4 ; i++){
tmp[i] = fgetc(fp);
}
I made this tmp array, but I need 0x0026c020.
how can I change this array to that value? or please suggest me better algorithm.
Thanks.
If you know for a fact that the value is stored with the same endianness as the host OS architecture, you can just do:
int value = *(int *)tmp;
However, you should not read the bytes in backwards order, as you do here -- that alters the endianness and will result in an incorrect value. Try this:
int value;
if (fread(&value, sizeof(value), 1, fp) != 1) {
/* Could not read, handle error. */
}
/* value is set, inspect it */
To convert a string into integer there are already available functions one such function is
strtoul().
you can use standard strtoul() function to convert string into integer values.