Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does sprintf/snprintf allocate additional memory?

I'm writing a library and want to make it absolutely resource-agnostic which also means that library should live with user-supplied memory allocation functions. Library allows user to set their own error handler function too, which are called with an error message as an argument, like that:

typedef void (*error_handler)(const char* msg);

Library code prepares error message by itself, somehow like that (with case when message formatting fails being omitted):

char buf[BUF_SIZE];
snprintf(buf, BUF_SIZE, "Oops found at file '%s' line %d", __FILE__, __LINE__);

But can I be sure that snprintf will not allocate even more memory for its internal usage with malloc, obviously bypassing user-supplied allocation routines? Man page in my Linux system keeps silence on that.

like image 887
firegurafiku Avatar asked Feb 17 '15 20:02

firegurafiku


1 Answers

According to the glibc, newlibc source code, both of them use malloc under some circumstances, but not in the likeliest cases.

If you want to find out whenever the current code executes malloc, or any other function, you can hook in the libc functions like this on Linux:

#define _GNU_SOURCE

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

void *malloc(size_t size) {
    static void *(*original_malloc)(size_t) = NULL;
    if (! original_malloc) {
        /* get the pointer to the original malloc */
        original_malloc = dlsym(RTLD_NEXT, "malloc");
    }

    void *rv = original_malloc(size);
    printf("allocated %zd bytes of memory\n", size);
    return rv;
}

Compile this into a shared object with

gcc -Wl,--no-as-needed -shared -ldl -fPIC hook.c -o hook.so

And given the code

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

int main() {
    char buf[256];
    char *malloced;

    printf("about to run sprintf\n");
    sprintf(buf, "%.250f", 0.123456789);
    printf("done\n");

    printf("about to run asprintf\n");
    asprintf(&malloced, "foo");
    free(malloced);
    printf("done\n");
}

compiled into prog, you can run it:

% LD_PRELOAD=./hook.so ./prog
about to run sprintf
done
about to run asprintf
allocated 100 bytes of memory
allocated 4 bytes of memory
done
like image 133