improve xattr code

Sat, 20 Apr 2024 12:43:44 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sat, 20 Apr 2024 12:43:44 +0200
changeset 813
06cf17795b86
parent 812
5fe4453fc025
child 814
0ce45bdc48bc

improve xattr code

- check allocation return value
- xattr_get returns null terminated strings

dav/libxattr.c file | annotate | diff | comparison | revisions
--- a/dav/libxattr.c	Wed Apr 10 22:07:17 2024 +0200
+++ b/dav/libxattr.c	Sat Apr 20 12:43:44 2024 +0200
@@ -1,29 +1,23 @@
 /*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright 2018 Olaf Wintermann. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- *   1. Redistributions of source code must retain the above copyright
- *      notice, this list of conditions and the following disclaimer.
+ * Copyright 2019 Olaf Wintermann
  *
- *   2. Redistributions in binary form must reproduce the above copyright
- *      notice, this list of conditions and the following disclaimer in the
- *      documentation and/or other materials provided with the distribution.
+ * Permission is hereby granted, free of charge, to any person obtaining a 
+ * copy of this software and associated documentation files (the "Software"), 
+ * to deal in the Software without restriction, including without limitation 
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, 
+ * and/or sell copies of the Software, and to permit persons to whom the 
+ * Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in 
+ * all copies or substantial portions of the Software.
  *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * DEALINGS IN THE SOFTWARE.
  */
 
 #define _GNU_SOURCE
@@ -42,13 +36,34 @@
 #define LIST_ARRAY_LEN 8
 #define ATTR_BUF_LEN 1024
 
-#define ARRAY_ADD(array, pos, len, obj) if(pos >= len) { \
-        len *= 2; /* TODO: missing error handling for realloc() */ \
-        array = realloc(array, len * sizeof(char*)); \
-    } \
-    array[pos] = obj; \
-    pos++;
 
+static int strarray_add(char ***array_ptr, size_t *pos, size_t *len, char *str) {
+    char **array = *array_ptr;
+    size_t array_pos = *pos;
+    size_t array_len = *len;
+    if(array_pos >= array_len) {
+        size_t newlen = array_len * 2;
+        char **new_array = NULL; //realloc(array, newlen * sizeof(char*));
+        if(!new_array) {
+            return 1;
+        }
+        *len = array_len;
+        array = new_array;
+        *array_ptr = new_array;
+    }
+    
+    array[array_pos] = str;
+    *pos = array_pos + 1;
+    
+    return 0;
+}
+
+static void strarray_free(char **array, size_t nelm) {
+    for(size_t i=0;i<nelm;i++) {
+        free(array[i]);
+    }
+    free(array);
+}
 
 #ifdef __linux__
 #define XATTR_SUPPORTED
@@ -63,13 +78,15 @@
     char *name = NULL;
     for(int i=0;i<length;i++) {
         if(!name && buf[i] == '.') {
-            int nslen = (buf+i-begin);
-            //printf("%.*s\n", nslen, begin);
             name = buf + i + 1;
         }
         if(buf[i] == '\0') {
             char *attrname = strdup(name);
-            ARRAY_ADD(array, arraypos, arraylen, attrname);
+            if(strarray_add(&array, &arraypos, &arraylen, attrname)) {
+                strarray_free(array, arraypos);
+                *nelm = -1;
+                return NULL;
+            }
             begin = buf + i + 1;
             name = 0;
         }
@@ -86,6 +103,10 @@
 
 char ** xattr_list(const char *path, ssize_t *nelm) {
     char *list = malloc(LIST_BUF_LEN);
+    if(!list) {
+        *nelm = -1;
+        return NULL;
+    }
     ssize_t len = listxattr(path, list, LIST_BUF_LEN);
     if(len == -1) {
         switch(errno) {
@@ -94,7 +115,13 @@
                 ssize_t newlen = listxattr(path, NULL, 0);
                 if(newlen > 0) {
                     // second try
-                    list = realloc(list, newlen);
+                    char *new_list = realloc(list, newlen);
+                    if(!new_list) {
+                        free(list);
+                        *nelm = -1;
+                        return NULL;
+                    }
+                    list = new_list;
                     len = listxattr(path, list, newlen);
                     if(len != -1) {
                         // this time it worked
@@ -128,7 +155,11 @@
     char *attrname = name2nsname(attr);
     
     char *buf = malloc(ATTR_BUF_LEN);
-    ssize_t vlen = getxattr(path, attrname, buf, ATTR_BUF_LEN);
+    if(!buf) {
+        *len = -1;
+        return NULL;
+    }
+    ssize_t vlen = getxattr(path, attrname, buf, ATTR_BUF_LEN - 1);
     if(vlen < 0) {
         switch(errno) {
             case ERANGE: {
@@ -136,6 +167,11 @@
                 if(attrlen > 0) {
                     free(buf);
                     buf = malloc(attrlen + 1);
+                    if(!buf) {
+                        *len = -1;
+                        free(attrname);
+                        return NULL;
+                    }
                     vlen = getxattr(path, attrname, buf, attrlen);
                     if(vlen > 0) {
                         break;
@@ -150,9 +186,9 @@
             }
         }
     }
+    buf[vlen] = 0;
     
     free(attrname);
-    buf[vlen] = 0;
     *len = vlen;
     return buf;
 }
@@ -186,7 +222,11 @@
     for(int i=0;i<length;i++) {
         if(buf[i] == '\0') {
             char *attrname = strdup(name);
-            ARRAY_ADD(array, arraypos, arraylen, attrname);
+            if(strarray_add(&array, &arraypos, &arraylen, attrname)) {
+                strarray_free(array, arraypos);
+                *nelm = -1;
+                return NULL;
+            }
             name = buf + i + 1;
         }
     }
@@ -202,6 +242,10 @@
 
 char ** xattr_list(const char *path, ssize_t *nelm) {
     char *list = malloc(LIST_BUF_LEN);
+    if(!list) {
+        *nelm = -1;
+        return NULL;
+    }
     ssize_t len = listxattr(path, list, LIST_BUF_LEN, 0);
     if(len == -1) {
         switch(errno) {
@@ -210,7 +254,13 @@
                 ssize_t newlen = listxattr(path, NULL, 0, 0);
                 if(newlen > 0) {
                     // second try
-                    list = realloc(list, newlen);
+                    char *new_list = realloc(list, newlen);
+                    if(!new_list) {
+                        free(list);
+                        *nelm = -1;
+                        return NULL;
+                    }
+                    list = new_list;
                     len = listxattr(path, list, newlen, 0);
                     if(len != -1) {
                         // this time it worked
@@ -240,14 +290,18 @@
     }
     
     char *buf = malloc(attrlen + 1);
+    if(!buf) {
+        *len = -1;
+        return NULL;
+    }
     ssize_t vlen = getxattr(path, attr, buf, attrlen, 0, 0);
     if(vlen < 0) {
         *len = -1;
         free(buf);
         return NULL;
     }
+    buf[vlen] = 0;
     
-    buf[attrlen] = 0;
     *len = vlen;
     return buf;
 }
@@ -299,6 +353,11 @@
     size_t arraylen = LIST_ARRAY_LEN;
     size_t arraypos = 0;
     char **array = malloc(LIST_ARRAY_LEN * sizeof(char*));
+    if(!array) {
+        closedir(dir);
+        *nelm = -1;
+        return NULL;
+    }
     
     struct dirent *ent;
     while((ent = readdir(dir)) != NULL) {
@@ -306,7 +365,12 @@
             continue;
         }
         char *name = strdup(ent->d_name);
-        ARRAY_ADD(array, arraypos, arraylen, name);
+        if(strarray_add(&array, &arraypos, &arraylen, name)) {
+            strarray_free(array, arraypos);
+            *nelm = -1;
+            closedir(dir);
+            return NULL;
+        }
     }
     closedir(dir);
     
@@ -330,7 +394,10 @@
     
     size_t bufsize = (size_t)s.st_size;
     char *buf = malloc(bufsize + 1);
-    buf[bufsize] = 0;
+    if(!buf) {
+        close(attrfile);
+        return NULL;
+    }
     
     char *b = buf;
     size_t cur = 0;
@@ -348,6 +415,7 @@
         return NULL;
     }
     
+    buf[cur] = 0;
     *len = (ssize_t)bufsize;
     return buf;    
 }
@@ -398,14 +466,27 @@
     size_t arraylen = LIST_ARRAY_LEN;
     size_t arraypos = 0;
     char **array = malloc(LIST_ARRAY_LEN * sizeof(char*));
+    if(!array) {
+        *nelm = -1;
+        return NULL;
+    }
     
     for(int i=0;i<length;i++) {
-        char namelen = buf[i];
+        int namelen = buf[i];
         char *name = buf + i + 1;
         char *attrname = malloc(namelen + 1);
+        if(!attrname) {
+            strarray_free(array, arraypos);
+            *nelm = -1;
+            return NULL;
+        }
         memcpy(attrname, name, namelen);
         attrname[namelen] = 0;
-        ARRAY_ADD(array, arraypos, arraylen, attrname);
+        if(strarray_add(&array, &arraypos, &arraylen, attrname)) {
+            strarray_free(array, arraypos);
+            *nelm = -1;
+            return NULL;
+        }
         i += namelen;
     }
     
@@ -429,6 +510,9 @@
     }
     
     char *list = malloc(lslen);
+    if(!list) {
+        return NULL;
+    }
     ssize_t len = extattr_list_file(path, EXTATTR_NAMESPACE_USER, list, lslen);
     if(len == -1) {
         free(list);

mercurial