Commit ec9a02a239d42b24a897e985c7cd3c3833d68f33

Pino Toscano 2013-07-24T10:05:02

Get rid of the usage of PATH_MAX PATH_MAX is optional in POSIX, so avoid its unconditional usage allocating and freeing buffers as needed. To avoid too many malloc/free in the for loop in FindFileInXkbPath, a buffer is grown according to the size needed at each iteration.

diff --git a/src/xkbcomp/include.c b/src/xkbcomp/include.c
index b4a4014..280bbbd 100644
--- a/src/xkbcomp/include.c
+++ b/src/xkbcomp/include.c
@@ -199,17 +199,34 @@ FindFileInXkbPath(struct xkb_context *ctx, const char *name,
 {
     unsigned int i;
     FILE *file = NULL;
-    char buf[PATH_MAX];
+    char *buf = NULL;
     const char *typeDir;
+    size_t buf_size = 0, typeDirLen, name_len;
 
     typeDir = DirectoryForInclude(type);
+    typeDirLen = strlen(typeDir);
+    name_len = strlen(name);
 
     for (i = 0; i < xkb_context_num_include_paths(ctx); i++) {
-        int ret = snprintf(buf, sizeof(buf), "%s/%s/%s",
-                           xkb_context_include_path_get(ctx, i),
-                           typeDir, name);
-        if (ret >= (ssize_t) sizeof(buf)) {
-            log_err(ctx, "File name (%s/%s/%s) too long\n",
+        size_t new_buf_size = strlen(xkb_context_include_path_get(ctx, i)) +
+                              typeDirLen + name_len + 3;
+        int ret;
+        if (new_buf_size > buf_size) {
+            void *buf_new = realloc(buf, new_buf_size);
+            if (buf_new) {
+                buf_size = new_buf_size;
+                buf = buf_new;
+            } else {
+                log_err(ctx, "Cannot realloc for name (%s/%s/%s)\n",
+                        xkb_context_include_path_get(ctx, i), typeDir, name);
+                continue;
+            }
+        }
+        ret = snprintf(buf, buf_size, "%s/%s/%s",
+                       xkb_context_include_path_get(ctx, i),
+                       typeDir, name);
+        if (ret < 0) {
+            log_err(ctx, "snprintf error (%s/%s/%s)\n",
                     xkb_context_include_path_get(ctx, i), typeDir, name);
             continue;
         }
@@ -242,11 +259,14 @@ FindFileInXkbPath(struct xkb_context *ctx, const char *name,
                         xkb_context_failed_include_path_get(ctx, i));
         }
 
+        free(buf);
         return NULL;
     }
 
     if (pathRtrn)
-        *pathRtrn = strdup(buf);
+        *pathRtrn = buf;
+    else
+        free(buf);
     return file;
 }
 
diff --git a/test/common.c b/test/common.c
index 7b4ee00..796904e 100644
--- a/test/common.c
+++ b/test/common.c
@@ -138,13 +138,22 @@ test_key_seq(struct xkb_keymap *keymap, ...)
     return ret;
 }
 
-const char *
+char *
 test_get_path(const char *path_rel)
 {
-    static char path[PATH_MAX];
+    char *path;
+    size_t path_len;
     const char *srcdir = getenv("srcdir");
 
-    snprintf(path, PATH_MAX - 1,
+    path_len = strlen(srcdir ? srcdir : ".") +
+               strlen(path_rel ? path_rel : "") + 12;
+    path = malloc(path_len);
+    if (!path) {
+        fprintf(stderr, "Failed to allocate path (%d chars) for %s\n",
+                (int) path_len, path);
+        return NULL;
+    }
+    snprintf(path, path_len,
              "%s/test/data/%s", srcdir ? srcdir : ".",
              path_rel ? path_rel : "");
 
@@ -155,10 +164,15 @@ char *
 test_read_file(const char *path_rel)
 {
     struct stat info;
-    char *ret, *tmp;
+    char *ret, *tmp, *path;
     int fd, count, remaining;
 
-    fd = open(test_get_path(path_rel), O_RDONLY);
+    path = test_get_path(path_rel);
+    if (!path)
+        return NULL;
+
+    fd = open(path, O_RDONLY);
+    free(path);
     if (fd < 0)
         return NULL;
 
@@ -195,6 +209,7 @@ test_get_context(enum test_context_flags test_flags)
 {
     enum xkb_context_flags ctx_flags;
     struct xkb_context *ctx;
+    char *path;
 
     ctx_flags = XKB_CONTEXT_NO_DEFAULT_INCLUDES;
     if (test_flags & CONTEXT_ALLOW_ENVIRONMENT_NAMES) {
@@ -212,7 +227,12 @@ test_get_context(enum test_context_flags test_flags)
     if (!ctx)
         return NULL;
 
-    xkb_context_include_path_append(ctx, test_get_path(""));
+    path = test_get_path("");
+    if (!path)
+        return NULL;
+
+    xkb_context_include_path_append(ctx, path);
+    free(path);
 
     return ctx;
 }
@@ -222,11 +242,16 @@ test_compile_file(struct xkb_context *context, const char *path_rel)
 {
     struct xkb_keymap *keymap;
     FILE *file;
-    const char *path = test_get_path(path_rel);
+    char *path;
+
+    path = test_get_path(path_rel);
+    if (!path)
+        return NULL;
 
     file = fopen(path, "r");
     if (!file) {
         fprintf(stderr, "Failed to open path: %s\n", path);
+        free(path);
         return NULL;
     }
     assert(file != NULL);
@@ -237,10 +262,12 @@ test_compile_file(struct xkb_context *context, const char *path_rel)
 
     if (!keymap) {
         fprintf(stderr, "Failed to compile path: %s\n", path);
+        free(path);
         return NULL;
     }
 
     fprintf(stderr, "Successfully compiled path: %s\n", path);
+    free(path);
 
     return keymap;
 }
diff --git a/test/test.h b/test/test.h
index 804606e..95afbea 100644
--- a/test/test.h
+++ b/test/test.h
@@ -49,7 +49,7 @@ test_key_seq(struct xkb_keymap *keymap, ...);
 int
 test_key_seq_va(struct xkb_keymap *keymap, va_list args);
 
-const char *
+char *
 test_get_path(const char *path_rel);
 
 char *