It's displaying "junk" because of two errors:
- you don't allocate enough memory for the content plus the
'\0'-terminating byte.
- you don't set the '\0'-terminating byte.freadwon't do that becausefreaddoesn't care about the meaning of the bytes it's reading, it just reads
a block of memory and that's it.
int readfile(char **buffer, const char *input)
{
    if(buffer == NULL)
        return 0;
    FILE *file = fopen(input, "r");
    if(file == NULL)
    {
        fprintf(stderr, "could not open %s for reading: %s\n", input,
                strerror(errno));
        return 0;
    }
    int bytes = filesize(file);
    *buffer = malloc(bytes + 1);
    if(*buffer == NULL)
    {
        fprintf(stderr, "Not enough memory\n");
        fclose(file);
        return 0;
    }
    if(fread(*buffer, bytes, 1, file) != 1)
    {
        fprintf(stderr, "could not read\n");
        free(*buffer);
        *buffer = NULL;
        fclose(file);
        return 0;
    }
    (*buffer)[bytes] = 0; // setting the 0 byte
    puts(*buffer);
    fclose(file);
    return 1;
}
You should also always check the return code of functions, specially those that
return pointers and/or write to a pointer you passed them. If one of the
functions returns an error, you would have undefined behaviour otherwise.
edit
in the comments you said
I tried this by doing *buffer[bytes-1] = '\0'; but it just crashed the program when it tried to do this 
that's because buffer[bytes-1] is the same as buffer + bytes -1 and this
beyond the bound of where buffer is pointing. When you try to dereference it
with *, it will crash. You you need to do (like I did in the code) is:
(*buffer)[bytes] = 0; which is the same as buffer[0][bytes] = 0.