fix dav-sync push creating finfo elements without using the mempool, which could lead to crashes

Mon, 09 Aug 2021 17:22:21 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Mon, 09 Aug 2021 17:22:21 +0200
changeset 736
40be8db6fe45
parent 735
74a6e2d4fb1f
child 737
1c75c0498520

fix dav-sync push creating finfo elements without using the mempool, which could lead to crashes

dav/finfo.c file | annotate | diff | comparison | revisions
dav/version.h file | annotate | diff | comparison | revisions
libidav/resource.c file | annotate | diff | comparison | revisions
libidav/webdav.h file | annotate | diff | comparison | revisions
libidav/xml.c file | annotate | diff | comparison | revisions
test/bin-test/test-dav-sync-metadata1.sh file | annotate | diff | comparison | revisions
--- a/dav/finfo.c	Sun Aug 08 16:50:36 2021 +0200
+++ b/dav/finfo.c	Mon Aug 09 17:22:21 2021 +0200
@@ -101,7 +101,7 @@
         char str[32];
         struct tm *date = gmtime(&s->st_mtime);
         strftime(str, 32, "%a, %d %b %Y %H:%M:%S GMT", date);
-        DavXmlNode *mtime = dav_xml_createnode_with_text(DAV_PROPS_NS, "mtime", str);
+        DavXmlNode *mtime = dav_text_element(res->session, DAV_PROPS_NS, "mtime", str);
         content = mtime;
         last = mtime;
     }
@@ -113,7 +113,7 @@
         mode_t mode = s->st_mode & 07777;
         char str[32];
         snprintf(str, 32, "%o", (int)mode);
-        DavXmlNode *xmode = dav_xml_createnode_with_text(DAV_PROPS_NS, "mode", str);
+        DavXmlNode *xmode = dav_text_element(res->session, DAV_PROPS_NS, "mode", str);
         if(last) {
             last->next = xmode;
         } else {
--- a/dav/version.h	Sun Aug 08 16:50:36 2021 +0200
+++ b/dav/version.h	Mon Aug 09 17:22:21 2021 +0200
@@ -27,6 +27,6 @@
  */
 
 #ifndef DAV_VERSION
-#define DAV_VERSION "1.3.0"
+#define DAV_VERSION "2.0 dev"
 #endif
 
--- a/libidav/resource.c	Sun Aug 08 16:50:36 2021 +0200
+++ b/libidav/resource.c	Mon Aug 09 17:22:21 2021 +0200
@@ -153,7 +153,7 @@
         dav_session_free(sn, p->ns);
         
         dav_session_free(sn, p->name);
-        dav_session_free(sn, p->value);
+        dav_free_xml_node_sn(sn, p->value);
         dav_session_free(sn, p);
     }
     
@@ -600,7 +600,9 @@
     DavResourceData *data = res->data;
     
     DavProperty *property = createprop(sn, ns, name);
-    property->value = value; // TODO: copy node?
+    // TODO: this function should copy the value
+    //       but we also need a function, that doesn't create a copy
+    property->value = value;
     
     if(DAV_ENCRYPT_PROPERTIES(sn) && dav_namespace_is_encrypted(sn->context, ns)) {
         data->crypto_set = ucx_list_append_a(a, data->crypto_set, property);
--- a/libidav/webdav.h	Sun Aug 08 16:50:36 2021 +0200
+++ b/libidav/webdav.h	Mon Aug 09 17:22:21 2021 +0200
@@ -362,10 +362,14 @@
 char* dav_xml_getstring(DavXmlNode *node);
 DavBool dav_xml_isstring(DavXmlNode *node);
 DavXmlNode* dav_xml_nextelm(DavXmlNode *node);
-DavXmlNode* dav_text_node(DavSession *sn, char *text);
+DavXmlNode* dav_text_node(DavSession *sn, const char *text);
+DavXmlNode* dav_text_element(DavSession *sn, const char *ns, const char *name, const char *text);
 
 DavXmlNode* dav_copy_node(DavXmlNode *node);
 
+void dav_free_xml_node_sn(DavSession *sn, DavXmlNode *node);
+void dav_free_xml_node(DavXmlNode *node);
+
 DavXmlNode* dav_xml_createnode(const char *ns, const char *name);
 DavXmlNode* dav_xml_createnode_with_text(const char *ns, const char *name, const char *text);
 DavXmlNode* dav_xml_createtextnode(const char *text);
--- a/libidav/xml.c	Sun Aug 08 16:50:36 2021 +0200
+++ b/libidav/xml.c	Mon Aug 09 17:22:21 2021 +0200
@@ -240,16 +240,52 @@
     return NULL;
 }
 
-DavXmlNode* dav_text_node(DavSession *sn, char *text) {
+DavXmlNode* dav_text_node(DavSession *sn, const char *text) {
     UcxMempool *mp = sn->mp; 
     DavXmlNode *newxn = ucx_mempool_calloc(mp, 1, sizeof(DavXmlNode));
     newxn->type = DAV_XML_TEXT;
-    sstr_t content = sstrdup_a(mp->allocator, sstr(text));
+    sstr_t content = scstrdup_a(mp->allocator, scstr(text));
     newxn->content = content.ptr;
     newxn->contentlength = content.length;
     return newxn;
 }
 
+DavXmlNode* dav_text_element(DavSession *sn, const char *ns, const char *name, const char *text) {
+    UcxMempool *mp = sn->mp; 
+    DavXmlNode *newelm = ucx_mempool_calloc(mp, 1, sizeof(DavXmlNode));
+    newelm->type = DAV_XML_ELEMENT;
+    newelm->namespace = scstrdup_a(mp->allocator, scstr(ns)).ptr;
+    newelm->name = scstrdup_a(mp->allocator, scstr(name)).ptr;
+    newelm->children = dav_text_node(sn, text);
+    return newelm;
+}
+
+static void dav_free_xml_node_a(UcxAllocator *a, DavXmlNode *node) {
+    if(node->name) alfree(a, node->name);
+    if(node->namespace) alfree(a, node->namespace);
+    if(node->content) alfree(a, node->content);
+    DavXmlAttr *attr = node->attributes;
+    while(attr) {
+        if(attr->name) alfree(a, attr->name);
+        if(attr->value) alfree(a, attr->value);
+        attr = attr->next;
+    }
+    DavXmlNode *children = node->children;
+    while(children) {
+        DavXmlNode *next_ch = children->next;
+        dav_free_xml_node_a(a, children);
+        children = next_ch;
+    }
+    alfree(a, node);
+}
+
+void dav_free_xml_node_sn(DavSession *sn, DavXmlNode *node) {
+    dav_free_xml_node_a(sn->mp->allocator, node);
+}
+
+void dav_free_xml_node(DavXmlNode *node) {
+    dav_free_xml_node_a(ucx_default_allocator(), node);
+}
 
 DavXmlAttr* dav_copy_xml_attr(DavXmlAttr *attr) {
     if(!attr) {
--- a/test/bin-test/test-dav-sync-metadata1.sh	Sun Aug 08 16:50:36 2021 +0200
+++ b/test/bin-test/test-dav-sync-metadata1.sh	Mon Aug 09 17:22:21 2021 +0200
@@ -38,6 +38,14 @@
 	exit 1
 fi
 
+TEST=`uname | grep BSD`
+if [ $? -eq 0 ];
+then
+	alias stat_="stat -f %m"
+else
+	alias stat_="stat -c %Y"
+fi
+
 XATTR=../../build/xattrtool
 
 # checks if tmp-sync/out.txt contains a specific text
@@ -151,11 +159,11 @@
 check_tmpout "0 conflicts" "test 2: wrong conflict counter (pull)"
 check_tmpout "0 errors" "test 2: wrong error counter (pull)"
 
-MTIMEA1=`stat -c %Y tmp-sync/test4a/file1`
-MTIMEB1=`stat -c %Y tmp-sync/test4b/file1`
+MTIMEA1=`stat_ tmp-sync/test4a/file1`
+MTIMEB1=`stat_ tmp-sync/test4b/file1`
 
-MTIMEA2=`stat -c %Y tmp-sync/test4a/dir1/file2`
-MTIMEB2=`stat -c %Y tmp-sync/test4b/dir1/file2`
+MTIMEA2=`stat_ tmp-sync/test4a/dir1/file2`
+MTIMEB2=`stat_ tmp-sync/test4b/dir1/file2`
 
 if [ $MTIMEA1 != $MTIMEB1 ]; then
 	echo "file1: mtime not synced"
@@ -183,8 +191,8 @@
 check_tmpout "0 conflicts" "test 3: wrong conflict counter (pull)"
 check_tmpout "0 errors" "test 3: wrong error counter (pull)"
 
-MTIMEA1=`stat -c %Y tmp-sync/test4a/file1`
-MTIMEB1=`stat -c %Y tmp-sync/test4b/file1`
+MTIMEA1=`stat_ tmp-sync/test4a/file1`
+MTIMEB1=`stat_ tmp-sync/test4b/file1`
 
 if [ $MTIMEA1 != $MTIMEB1 ]; then
 	echo "file1: mtime not synced"

mercurial