0

It's kinda heard to explain... i'll give an example:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main()
{
    int len;
    char* str_input;

    printf("Enter len of str: ");
    scanf("%d", &len);

    str_input = (char*) malloc(len * sizeof(char));

    printf("Enter str. & to end: ");
    scanf("%s", str_input);

    printf("%s", str_input);
}

The above code asks me to enter a length. Suppose I enter 1. then I allocate a memory of 1 byte. Then it asks me for a string. I enter something with length more than 1, for example "hello". And print it. And it prints the entire string "hello"!. Why does this happen? should the program crash because there isn't enough memory?

How do I fix this?

nat34
  • 3
  • 5
  • 1
    Exceeding the allocated memory is undefined behavior. Sometimes it works, sometimes it crashes. – sj95126 Oct 25 '22 at 18:39
  • 1
    It's called Undefined Behavior. C will happily let you shoot yourself in the foot in this way and many others. – 001 Oct 25 '22 at 18:39
  • So there is no way I can solve it? I should just let the user input a string of a length more than he entered? – nat34 Oct 25 '22 at 18:40
  • 1
    If you want to read exactly `n` characters, use `fread`, not `scanf`. – rici Oct 25 '22 at 18:41
  • 2
    Yes, this is a known issue with `scanf`, If you did: `char buf[10];` you could do: `scanf("%9s",buf);` But, it's tricky with a dynamic length. You'd have to do: `char fmt[10]; sprintf(fmt,"%%%ds",len - 1); scanf(fmt,str_input);` And, this won't work too well if `len` is 1. You could use `getline` or `fgets`. But, don't mix `scanf` with `getline`, `getchar`, `fgets`, etc. See my answer: [Check if all values entered into char array are numerical](https://stackoverflow.com/a/65013419/5382650) – Craig Estey Oct 25 '22 at 18:41
  • But note that you cannot stop the user from typing more characters. All you can do is fail to read them with this particular function call. If they type more, the remaining characters will be left for the next read operation. – rici Oct 25 '22 at 18:42
  • Anyway, why would you want to force the user to count the number of characters they are about to type? That seems like an incredibly inconvenient user interface. Let them type as they please, and then your program can figure out how many characters they typed. (As Craig says, you can use `getline`.) – rici Oct 25 '22 at 18:45
  • Please note also that a 1-byte allocated region is only large enough for the null-string `""`. The string, `"A"` by contrast is 2-bytes long – Willis Hershey Oct 25 '22 at 18:51
  • Related: [No out of bounds error](https://stackoverflow.com/questions/9137157/no-out-of-bounds-error) – Weather Vane Oct 25 '22 at 18:55
  • `scanf` is simply not the correct tool, use `fgets` instead. – Pablo Oct 25 '22 at 18:55
  • 1
    The `%s` format string with `scanf` is as bad as `gets`, if not provided with a length. It is that *unsafe*. – Cheatah Oct 25 '22 at 18:57
  • ^^Pablo, when I tried fgets, if i exceeded the character limit in the input, it simply saved the input for the next fgets and causes problems, for example chars instead of ints when requesting for length. (The code above is not my original program, just a snippet.) – nat34 Oct 25 '22 at 19:04
  • 1
    So allocate a *generous* buffer. Don't be mean with your buffer sizes. They don't come out of your wages. If you are using `fgets` the buffer needs to be *at least* `2` bytes larger than the size entered. – Weather Vane Oct 25 '22 at 19:11
  • 1
    No matter how generous the allocation, it is always possible for the input to exceed it. Your program needs to deal with that. Even if you "deal with it" simply by aborting with an error message. But don't just let the user enter data that will arbitrarily overflow some buffer. This type of mistake is the cause of many security issues. – William Pursell Oct 25 '22 at 19:40

1 Answers1

0

The behavior on writing past the end of an array or dynamically allocated buffer is undefined - your code may crash outright, it may clobber other data, or it may work as expected with no apparent issues.

If the storage beyond your allocated buffer isn't being used by anything else, then writing into that storage won't cause any immediate problems. If that storage later gets allocated for something else, anything you wrote there will get clobbered.

C doesn't enforce any kinds of bounds checking on array accesses - it can't, because array size information isn't actually stored anywhere (with the exception of VLAs).

scanf has no way of knowing how big your target buffer is - all it sees is the address of the first byte of that buffer. All you can do is tell it to only read so many characters using a width specification in the format:

str_input = malloc( 10 * sizeof *str_input );
scanf( "%9s", str_input ); // leave one element for string terminator

It's up to you, the programmer, to enforce any array bounds. You have to store the array size yourself, and you have to perform all the bounds checks yourself.

John Bode
  • 119,563
  • 19
  • 122
  • 198