ccanlint: avoid segfault when module_builds' linking fails
authorPeter Barker <pb-ccan@barker.dropbear.id.au>
Fri, 10 Apr 2015 01:26:23 +0000 (11:26 +1000)
committerRusty Russell <rusty@rustcorp.com.au>
Fri, 10 Apr 2015 03:03:46 +0000 (12:33 +0930)
In the case that the objects built but linking failed, module_builds.c
called score_file_error with a NULL ccan_file object and 0 for line
number.

score_file_error assumed that the ccan_file object it is passed was
not-NULL when appending file errors to the score's aggregate error
string.  It attempted to dereference it to get "fullname".

score_error was factored out from score_file_error.  It takes a
"source" parameter, which is the file's full name (and possibly line
number) in the score_file_error case, and the ccan module name in the
case of link failure.

tools/ccanlint/ccanlint.h
tools/ccanlint/file_analysis.c
tools/ccanlint/tests/module_builds.c

index ae22fa8a8b7d5c3a8fb98841a911f8e6db6501fe..9cb858f7d6a02e715eda56ac38d92d133e846066 100644 (file)
@@ -152,6 +152,10 @@ char **per_file_options(const struct ccanlint *test, struct ccan_file *f);
 void score_file_error(struct score *, struct ccan_file *f, unsigned line,
                      const char *errorfmt, ...);
 
 void score_file_error(struct score *, struct ccan_file *f, unsigned line,
                      const char *errorfmt, ...);
 
+/* Append message to the score->error */
+void score_error(struct score *score, const char * source,
+                const char *errorfmt, ...);
+
 /* Start a command in the background. */
 void run_command_async(const void *ctx, unsigned int time_ms,
                       const char *fmt, ...);
 /* Start a command in the background. */
 void run_command_async(const void *ctx, unsigned int time_ms,
                       const char *fmt, ...);
index 8fbb7186c91213127837108228581c92dcac534f..abcf0795e7111dd3c4432332778e398cca05157a 100644 (file)
@@ -360,15 +360,9 @@ enum line_compiled get_ccan_line_pp(struct pp_conditions *cond,
        return ret;
 }
 
        return ret;
 }
 
-void score_file_error(struct score *score, struct ccan_file *f, unsigned line,
-                     const char *errorfmt, ...)
+static void score_error_vfmt(struct score *score, const char *source,
+                            const char *errorfmt, va_list ap)
 {
 {
-       va_list ap;
-
-       struct file_error *fe = tal(score, struct file_error);
-       fe->file = f;
-       fe->line = line;
-       list_add_tail(&score->per_file_errors, &fe->list);
 
        if (!score->error)
                score->error = tal_strdup(score, "");
 
        if (!score->error)
                score->error = tal_strdup(score, "");
@@ -384,17 +378,45 @@ void score_file_error(struct score *score, struct ccan_file *f, unsigned line,
                return;
        }
 
                return;
        }
 
+       tal_append_fmt(&score->error, "%s:", source);
+       tal_append_vfmt(&score->error, errorfmt, ap);
+       score->error = tal_strcat(score, take(score->error), "\n");
+}
+
+
+
+void score_error(struct score *score, const char *source,
+                const char *errorfmt, ...)
+{
+       va_list ap;
+
+       va_start(ap, errorfmt);
+       score_error_vfmt(score, source, errorfmt, ap);
+       va_end(ap);
+}
+
+void score_file_error(struct score *score, struct ccan_file *f, unsigned line,
+                     const char *errorfmt, ...)
+{
+       va_list ap;
+       char *source;
+
+       struct file_error *fe = tal(score, struct file_error);
+       fe->file = f;
+       fe->line = line;
+       list_add_tail(&score->per_file_errors, &fe->list);
+
        if (line)
        if (line)
-               tal_append_fmt(&score->error, "%s:%u:", f->fullname, line);
+               source = tal_fmt(score, "%s:%u", f->fullname, line);
        else
        else
-               tal_append_fmt(&score->error, "%s:", f->fullname);
+               source = tal_fmt(score, "%s", f->fullname);
 
        va_start(ap, errorfmt);
 
        va_start(ap, errorfmt);
-       tal_append_vfmt(&score->error, errorfmt, ap);
+       score_error_vfmt(score, source, errorfmt, ap);
        va_end(ap);
        va_end(ap);
-       score->error = tal_strcat(score, take(score->error),"\n");
 }
 
 }
 
+
 char *get_or_compile_info(const void *ctx, const char *dir)
 {
        struct manifest *m = get_manifest(NULL, dir);
 char *get_or_compile_info(const void *ctx, const char *dir)
 {
        struct manifest *m = get_manifest(NULL, dir);
index 45b67c5a5424373c4954aa1a106dc898a44da03e..cb13a0b63e6a53933705d9e3370f9237d8243238 100644 (file)
@@ -57,7 +57,7 @@ static void do_build(struct manifest *m,
        m->compiled[COMPILE_NORMAL]
                = build_module(m, COMPILE_NORMAL, &errstr);
        if (!m->compiled[COMPILE_NORMAL]) {
        m->compiled[COMPILE_NORMAL]
                = build_module(m, COMPILE_NORMAL, &errstr);
        if (!m->compiled[COMPILE_NORMAL]) {
-               score_file_error(score, NULL, 0, "%s", errstr);
+               score_error(score, m->modname,"%s", errstr);
                return;
        }
 
                return;
        }