Sat, 20 Apr 2024 12:43:44 +0200
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);