Fix: lttng-live: unbounded use of sscanf() in parse_url()
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Thu, 16 Jan 2014 19:52:24 +0000 (14:52 -0500)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Thu, 16 Jan 2014 19:52:24 +0000 (14:52 -0500)
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
formats/lttng-live/lttng-live.c

index 8f734f7bd9906e9f844bd86bd2cb4a21681dd318..b1ab7408415fb4265edc82b173da94af2f4bdb26 100644 (file)
 #include <stdlib.h>
 #include "lttng-live-functions.h"
 
+/*
+ * hostname parameter needs to hold NAME_MAX chars.
+ */
 static int parse_url(const char *path, char *hostname, int *port,
                uint64_t *session_id)
 {
-       char remain[NAME_MAX];
-       int ret, proto, proto_offset = 0;
-
-       ret = sscanf(path, "net%d%s", &proto, remain);
-       if (ret < 2) {
+       char remain[2][NAME_MAX];
+       int ret = -1, proto, proto_offset = 0;
+       size_t path_len = strlen(path);
+
+       /*
+        * Since sscanf API does not allow easily checking string length
+        * against a size defined by a macro. Test it beforehand on the
+        * input. We know the output is always <= than the input length.
+        */
+       if (path_len > NAME_MAX) {
+               goto end;
+       }
+       ret = sscanf(path, "net%d://", &proto);
+       if (ret < 1) {
                proto = 4;
                /* net:// */
                proto_offset = strlen("net://");
@@ -53,24 +65,39 @@ static int parse_url(const char *path, char *hostname, int *port,
                /* net4:// or net6:// */
                proto_offset = strlen("netX://");
        }
+       if (proto_offset > path_len) {
+               goto end;
+       }
        /* TODO : parse for IPv6 as well */
        /* Parse the hostname or IP */
-       ret = sscanf(path + proto_offset, "%[a-zA-Z.0-9%-]%s",
-               hostname, remain);
+       ret = sscanf(&path[proto_offset], "%[a-zA-Z.0-9%-]%s",
+               hostname, remain[0]);
        if (ret == 2) {
                /* Optional port number */
-               if (remain[0] == ':') {
-                       ret = sscanf(remain, ":%d%s", port, remain);
+               switch (remain[0][0]) {
+               case ':':
+                       ret = sscanf(remain[0], ":%d%s", port, remain[1]);
                        /* Optional session ID with port number */
                        if (ret == 2) {
-                               ret = sscanf(remain, "/%" PRIu64, session_id);
+                               ret = sscanf(remain[1], "/%" PRIu64,
+                                       session_id);
+                               /* Accept 0 or 1 (optional) */
+                               if (ret < 0) {
+                                       goto end;
+                               }
                        }
+                       break;
+               case '/':
                        /* Optional session ID */
-               } else if (remain[0] == '/') {
-                       ret = sscanf(remain, "/%" PRIu64, session_id);
-               } else {
+                       ret = sscanf(remain[0], "/%" PRIu64, session_id);
+                       /* Accept 0 or 1 (optional) */
+                       if (ret < 0) {
+                               goto end;
+                       }
+                       break;
+               default:
                        fprintf(stderr, "[error] wrong delimitor : %c\n",
-                               remain[0]);
+                               remain[0][0]);
                        ret = -1;
                        goto end;
                }
This page took 0.025162 seconds and 4 git commands to generate.