0

A function that reads file streams and prints them on-screen invokes undefined behavior and I am unable to localize the cause. This works if file, that contains less then two lines is loaded, otherwise it crashes.

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <inttypes.h>

char *getText (FILE* fp)
{
    uint_64 size;
    uint_64 i = 0;
    int chr;
    char *source;

    fseek(fp, 0L, SEEK_END);
    size = ftell(fp);

    source = calloc(size + 1, sizeof(char));

    fseek(fp, 0, SEEK_SET); // rewind

    while(chr != EOF)
        source[i++] = (chr = fgetc(fp));

    source[size] = '\0';    // Terminate string

    return(source);
}

int main(void)
{
    char sfile [256];
    FILE* fp;
    char *file;
    char buff [256];

    printf("Enter name of file: ");
    scanf("%s", sfile);

    if(!strncmp(sfile, "read-", strlen("read-")))
    {
        fp = fopen(sfile + strlen("read-"), "r");
        file = getText(fp);

        sprintf(buff, file);
        printf(buff);

        fclose(fp);
        free(file);
    }

    return 0;
}
Alan Salios
  • 241
  • 2
  • 9
  • 1
    You'll need to be a bit more specific than 'undefined behavior'. What does the program do? Is it deterministic (always does the same thing, or follows some pattern)? What debugging have you already tried? – aruisdante Jan 31 '15 at 22:51
  • I determined that it crashes if lines of the file stream > 2 and I described this already. The program usually crashes immediately.. sometimes it crashes with delay.. sometimes on terminating, sometimes the text appears and then crashes, sometimes it doesn't appear at all.. – Alan Salios Jan 31 '15 at 22:53
  • have you tried using gdb to see *why* it's crashing? Do you get any particular error text when it crashes? Are you sure it's not just terminating cleanly in a way you don't expect? – aruisdante Jan 31 '15 at 22:58
  • I am an experienced programmer. The program clearly does have a problem. I haven't tried much.. it works fine, compiled with mingw.. However this is a thing implemented in an old SDL-based engine. I don't know much of the old problems.. so I am looking for suggestions what could possibly be the cause of a crash in the code provided bellow. I reconstructed it a bit in order to make it compatible for regular compilation. – Alan Salios Jan 31 '15 at 23:01
  • Reconstructed? So is it your crashing code or not? I don't see how you can even get past the wierd filename test, since `scanf()` will stop at the first `space` you are expecting to be present in `"read "` and the file can never be even opened. – Weather Vane Jan 31 '15 at 23:12
  • I only added some code in main, because the real code doesn't have main... lets assume `scanf` will not stop on the first space.. this is really not important the program is in the code. It crashes because of it.. – Alan Salios Jan 31 '15 at 23:17
  • Yes, it *is* important, because we don't know what you are "guessing" that "should" work. Please post a minimal, compilable, etc that demonstrates the fault. – Weather Vane Jan 31 '15 at 23:18
  • This is minimal and compilable.. but with modern compilers from scratch.. I don't know if it will demonstrate the fault. It is fact that something is not good.. and I am looking to find out what. – Alan Salios Jan 31 '15 at 23:20
  • ...but not executable. – Weather Vane Jan 31 '15 at 23:21
  • Why would you need to compile it anyway.. If you want to test different things don't, because I can do that by myself. – Alan Salios Jan 31 '15 at 23:23
  • 1
    Am I the first one to side-note that you are executing `while(chr != EOF)` without first initializing `chr`? – barak manos Jan 31 '15 at 23:27
  • Won't that cause a problem only if `chr` has a default value of `-1` ? I think the chances are pretty small. – Alan Salios Jan 31 '15 at 23:28
  • That, and no check on the length of `i` (it may overrun), and the zero terminator is set at the wrong point. – Jongware Jan 31 '15 at 23:29
  • And by the way, since you've already obtained `size`, you might as well loop `for (i=0; i – barak manos Jan 31 '15 at 23:29
  • 1
    ... or use `fread` ... – Jongware Jan 31 '15 at 23:30
  • if the zero terminator is set on the wrong point then this could be a good reason. Yes.. I was thinking of using `fread` after all – Alan Salios Jan 31 '15 at 23:30
  • 1
    @AlanSalios: Considering that OP has specifically mentioned UB, I would take those chances rather seriously. – barak manos Jan 31 '15 at 23:31
  • @Jongware: Yep, even better. – barak manos Jan 31 '15 at 23:32

1 Answers1

0

After removing the irrelevant filename checking, the program crashes when the input file size is > 256 bytes, because of

char buff [256];
...
file = getText(fp);
...
sprintf(buff, file);
Weather Vane
  • 33,872
  • 7
  • 36
  • 56
  • Ahh yes.. well I don't exceed it. The real environment has a bit different usage of the function (it uses a built-in buffer instead). but that gave me an idea. As I was looking in the source code of the engine, that particular buffer was as such, statically allocated. So I might truly exceed it. – Alan Salios Jan 31 '15 at 23:38
  • `file = getText(fp);` assigns a pointer to a buffer allocated for the *entire* file. – Weather Vane Jan 31 '15 at 23:40
  • Yes. Yes it does. It should. – Alan Salios Jan 31 '15 at 23:41
  • Give us the "less than 2 lines" file content that does not crash, and the "more than 2 lines" file content that does crash. The limit is 255 bytes. If you need it spelling out, `getText()` allocates a buffer to contain the *whole file*, which you then `sprintf()` into a 256 char buffer. – Weather Vane Jan 31 '15 at 23:43
  • It actually has something to do with length of the line. This is the one that doesn't crash: http://hastebin.com/umuwirijop.css and the one that crashes is: http://hastebin.com/jepelicoma.hs – Alan Salios Jan 31 '15 at 23:56
  • I think I found the problem though. I don't know why does it do that I just know what is it. – Alan Salios Feb 01 '15 at 00:14