Vsprintf segmentation error using macros in C

I create a simple log library in CI there are three files

My example file:

  • example.c

Library files:

  • loglib.h
  • loglib.c

My main registration function is called logme. I defined different macros as wrappers to indicate different levels of logs:

eg,

  • WARN
  • ERROR
  • etc..

In example.c, I call macros:

int int_arg = 55;
WARN(1, "Warn message with level 1");
WARN(1, "Warn message with level %d", int_arg);

A macro is WARNdefined in loglib.h:

#define WARN(LEVEL, ...) \
    logme(LEVEL, 8, " <%s:%d> inside %s() -- "__VA_ARGS__, __FILE__, __LINE__, __func__);

And finally, the function logme:

void slog(int level, int flag, const char *msg, ...)
{
    char string[10000];
    bzero(string, sizeof(string));
    va_list args;
    va_start(args, msg);
    vsprintf(string, msg, args);
    va_end(args);

    // .. do other things
}

When I run the example file, this is what I get:

inside main () - Warn message with level 1

Segmentation error (kernel flushing)

I get a segmentation error when I call WARNwith formatted strings.

Segmentation error is displayed in vsprintf(string, msg, args);

Is this something wrong with my macro?

make :

CFLAGS = -g -O2 -Wall -lpthread
LIB = -lrt
OBJS = loglib.o

LIBINSTALL = /usr/local/lib
HEADINSTALL = /usr/local/include

.c.o:
    $(CC) $(CFLAGS) -c $< $(LIB)

libslog.a: $(OBJS)
    $(AR) rcs liblog.a $(OBJS)
    @echo [-] Syncing static library
    sync

install:
    @test -d $(LIBINSTALL) || mkdir $(LIBINSTALL)
    @test -d $(HEADINSTALL) || mkdir $(HEADINSTALL)
    @install -m 0664 liblog.a $(LIBINSTALL)/
    @install -m 0664 loglib.h $(HEADINSTALL)/
    @echo [-] Done

loglib.o: loglib.h

.PHONY: clean
clean:
    $(RM) liblog.a $(OBJS)
+4
4

:

/* 
 * SOURCE_THROW_LOCATION macro returns string which 
 * points to the file, as well as, the corresponding line 
 * of the caller function.
 */
#define LVL1(x) #x
#define LVL2(x) LVL1(x)
#define SOURCE_THROW_LOCATION "<"__FILE__":"LVL2(__LINE__)"> -- "

#define WARN(LEVEL, ...) \
    logme(LEVEL, FWARN, SOURCE_THROW_LOCATION __VA_ARGS__);
0

, __VA_ARGS__ :

#define WARN(LEVEL, ...) \
logme(LEVEL, 8, " <%s:%d> inside %s() -- "__VA_ARGS__, __FILE__, __LINE__, __func__);

: __FILE__ <%s .. WARN(), __VA_ARGS__. , . , __func__ , .

+1

logme. - .

#include <strings.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>

void logme(int level, int flag, const char *msg_preamble, const char* file, int line, const char* function, const char* msg, ... ) 
{
    char buffer1[10000];
    bzero(buffer1, sizeof(buffer1));
    sprintf(buffer1, msg_preamble, file, line, function);

    char buffer2[10000];
    bzero(buffer2, sizeof(buffer2));

    va_list args;
    va_start(args, msg);
    vsprintf(buffer2, msg, args);
    va_end(args);

    strcat(buffer1, buffer2);
    printf("%s\n", buffer1);
}

#define WARN(LEVEL, ...)                    \
  logme(LEVEL, 8, " <%s:%d> inside %s() -- ", __FILE__, __LINE__, __func__, __VA_ARGS__);

int main(int argc, char** argv) 
{
   int int_arg = 55;
   WARN(1, "Warn message with level 1");
   WARN(1, "Warn message with level %d", int_arg);
}
0

The order of the arguments is incorrect, so the format %sdoes not match the actual argument, and the program invokes undefined behavior.

Here is the corrected version of the macro WARN:

#define WARN(LEVEL, ...) \
    logme(LEVEL, 8, __FILE__, __LINE__, __func__, __VA_ARGS__);

And the corresponding function logme, using vsnprintf()instead vsprintf(), to avoid buffer overflows:

void slog(int level, int flag, const char *filename, in lineno,
          const char *funcname, const char *msg, ...) {
    char string[10000];
    int prefix;
    va_list args;

    // check level, flag..
    ...

    // format the message if needed
    prefix = snprintf(string, sizeof string, " <%s:%d> inside %s() -- ",
                      filename, lineno, funcname); 

    va_start(args, msg);
    vsnprintf(string + prefix, sizeof(string) - prefix, msg, args);
    va_end(args);

    // do other things
    ...
}
0
source

Source: https://habr.com/ru/post/1667478/


All Articles