-2

So I have a program

#include "main.h"
#import <limits.h>
#import <stdint.h>

int foo(const void *src, void *dst, uint16_t len)
{
    uint16_t index;
    const uint8_t *srcRef = src;
    uint8_t *dstRef = dst;

    for(index = 0; index <= len; index++)
    {
        dstRef[index] = srcRef[index];
        printf("-> %d - %d\n", index, srcRef[index]);
    }
    printf("%d\n", index);
    return 0;
}

int main()
{
    printf("max length of UInt16 is : %d\n", UINT16_MAX);
    uint8_t arrOr[55];
    uint8_t arr[55];
    arrOr[54] = 7;
    uint16_t len = 119;
    foo(arrOr, arr, len);
    return 0;
}

Is it normal for a program to be able to access an array index out out bounds? (I was actually expecting it to crash) It can access up to 119(120 crashes it) when array length is 55.

When it's 56, I can still only access up to 119 and 120 crashes it

When it's 57, I can access up to 135 and 136 crashes it.

I guess it's trying to access memory addresses given to the whole program and not just the array indexes. But what's actually happening when I change the array length to 57, that lets me access more addresses that I can't do by increasing it to 56?

Marco
  • 7,007
  • 2
  • 19
  • 49
Lord Stiltskin
  • 133
  • 1
  • 8
  • 4
    Please adjust your code so it won't contain words inappropriate to professional discourse. – StoryTeller - Unslander Monica Jan 03 '18 at 06:25
  • `#import ` ? – Stargateur Jan 03 '18 at 06:26
  • Are you sure this is the exact code you compiled? I think this won't compile without errors. – Ajay Brahmakshatriya Jan 03 '18 at 06:36
  • Wait... what the hack is `#import`? Visual Studio 2017 style? – iBug Jan 03 '18 at 06:36
  • @AjayBrahmakshatriya I think it will compile [in VS 2017](https://blogs.msdn.microsoft.com/vcblog/2017/05/05/cpp-modules-in-visual-studio-2017/). – iBug Jan 03 '18 at 06:37
  • 1
    Before you ask this question, ask yourself where would this ever be useful? Why would you ever access beyond your array bounds? – Ajay Brahmakshatriya Jan 03 '18 at 06:40
  • @Stargateur See [this comment](https://stackoverflow.com/questions/48072219/c-array-index-and-accessing-out-of-bounds/48072459#comment83118289_48072219) above. – iBug Jan 03 '18 at 06:53
  • @AjayBrahmakshatriya This was written on xcode. Just replace it with inlcude and it should compile fine. If you're also bothered by the datatype, replace the alias with the right datatype. – Lord Stiltskin Jan 03 '18 at 08:14
  • @AjayBrahmakshatriya If we were all just about the real life feasibility of code, some hideous bugs would never be discovered and exploits could never be developed. Although this little piece of code doesn't go to that extent, it's experimental and is used just for learning/tinkering. Programming is not just about checking if it's really useful in the real-life-context. – Lord Stiltskin Jan 03 '18 at 08:18
  • @LordStiltskin apart from the usefulness of 'I wrote bad code that I knew was bad but want it explained anyway', there is the other consideration: this out-of-bounds aray access Q. has been asked [FP overflow] times already:( – Martin James Jan 03 '18 at 12:32

2 Answers2

2

Looks like alignment matters.

First of all, this is undefined behavior so don't rely on it. Accessing out-of-bound is UB according to ISO C standard.

Warning again: Whatever below is highly implementation-dependent. Proceed at your own discretion.


Well, answer first. Your guess is right:

I guess it's trying to access memory addresses given to the whole program and not just the array indexes.

It's a bit interesting that your numbers 120 and 136 differs by 16, so I guess it's caused by an alignment of 8 (you have 2 arrays). In modern computers, data in memory is aligned for performance concerns. For a typical 64-bit system, it's aligned to 8, so both of your arrays arr and arrOr are aligned to 8 bytes. That is, when you declare a size of 57, it's actually taking up 64 bytes of memory (so you won't observe any difference if you declare a size between 57 and 64, but you will if it's 65).

For the extra space greater than 64, it's possibly because of the call stack. This means you're accessing the variables in parent functions like main or WinMain or whatever above. There's a few variables defined by the system when your program starts (hInstance, commandLine, hPrevInstance and so on, on Windows). When you access or even modify those memory area, you're risking breaking your program or even the whole system. Again that's one of the reasons why accessing out-of-bound is bad.

Last line (allow my repetitive note because it's important), this is implementation-dependent, and is subject to change when you compile the code on another platform, or even different versions of the same platform.

BTW, #import is not a standard preprocessor indicative. It's (most likely) only available in Visual Studio 2017. Don't do that later. I guess you're using VS 2017 on Windows based on that code.

iBug
  • 35,554
  • 7
  • 89
  • 134
  • 1
    We shouldn't keep telling nothing more than UB on these questions. It's important to know how the computer or a specific operating system work in addition to the fact that it's UB. – iBug Jan 03 '18 at 06:57
  • `LONG_BIT` indeed is 64 (so a word should be 8 bytes like you said). So what you're saying is that a new word is used for each of my arrays, right? Considering that each array element takes 8 bits, it does make sense. Is this kind of alignment/padding compiler dependent? – Lord Stiltskin Jan 03 '18 at 09:47
  • @LordStiltskin An array takes a space of a multiple of 8. That doesn't mean each element takes 8 bytes. Instead 8 elements share the same 8-byte word. If there's less than 8 elements then padding will fill that space up to a multiple of 8. – iBug Jan 03 '18 at 09:49
  • Regarding the `#import`, I did it on xcode. It's nothing serious actually. I won't use `#import` unless it's for just xcode. Sorry if it caused confusion. Also, if you have have resources for memory padding, alignment etc, please link me. Is there any tool, with which I can inspect memory(graphically)? Thank you very much for an actual reply. Others just kept ignoring the real question. They never got the real idea behind the question, tbh – Lord Stiltskin Jan 03 '18 at 09:51
0

Your Defined array and index is

uint8_t arrOr[55];

uint8_t arr[55];

index = 119;

which is out of array so you need to reduce index value or increase your array size so it's accessing out of memory location value i.e. garbage or some time segmentation fault

// accessing array out of bounds
#include <stdio.h>
int main()
{
    int arr[] = {1,2,3,4,5};
    printf("arr [0] is %d\n",arr[0]);
    printf("arr[10] is %d\n",arr[10]);
     
    // allocation memory to out of bound 
    // element
    arr[10] = 11;
    printf("arr[10] is %d\n",arr[10]);
    return 0;
}

Output : Runtime Error : Segmentation Fault (SIGSEGV)

Important Points:

-Stay inside the bounds of the array in C programming while using arrays to avoid any such errors. -C++ however offers the std::vector class template, which does not require to perform bounds checking. A vector also has the std::at() member function which can perform bounds-checking.

In case of java you can handle this exceptions easily using

java.lang.ArrayIndexOutOfBoundsException

Community
  • 1
  • 1
Sujay
  • 588
  • 6
  • 15
  • You missed the question though. My question clearly says that I'm aware I shouldn't intentionally be accessing such a memory. – Lord Stiltskin Jan 03 '18 at 08:25