Package: netcdf
Version: 4.1.3-7

The functions "nc_uriparse" in nc_uri.c and "ocuriparse" in ocuri.c (which are very, very similar to each other, almost copies) both don't check properly for malformed URIs. For example they cause a segmentation fault when given the URI "file:o/", "file://", "file://a" or "http://hostname/"; (the latter one indirectly through a null-pointer returned by the mentioned functions, which is then referenced in ocuribuild, when doing an "ocopen").

This causes bugs in downstream libraries and executables, e.g. in mincdump:
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=716119

As it's not fixed in the most recent upstream version (4.3.2), I tried to report the bug upstream (to the netcdf developers), but it looks like their bug tracking system is read-only, even after signing up (then what do they have it for anyway?). I'm gonna try via email now.

But as the Debian package is way behind upstream (sticking with 4.1.*), an upstream fix probably wouldn't help you, either. So I provided a patch to fix the problem.

Description: Fix checks for malformed URIs to avoid crashes
 The functions nc_uriparse and ocuriparse caused a segmentation fault
 when called on malformed URIs like "file:o/", "file://" or "file:///".
 This was due to: (1) An error in the check for the // part of the URI
 (between the "[protocol]:" and the hostname part), (2) a missing bail-out
 when the part containing file and constraints is missing. Besides, the fact
 that both functions set a null-pointer as file string when the file part
 was present, but empty (containing only one slash), caused a segmentation
 fault in ocuribuild when passing a URL like "http://domain.org/"; to ocopen.
Author: Martin Steghöfer <mar...@steghoefer.eu>

--- a/libdispatch/nc_uri.c
+++ b/libdispatch/nc_uri.c
@@ -115,7 +115,7 @@
     p += strlen(protocol);
 
     /* 5. skip // */
-    if(*p != '/' && *(p+1) != '/')
+    if(*p != '/' || *(p+1) != '/')
 	goto fail;
     p += 2;
 
@@ -123,6 +123,8 @@
     file = strchr(p,'/');
     if(file) {
 	*file++ = '\0'; /* warning: we just overwrote the leading / */
+    } else {
+        goto fail;
     }
 
     /* 7. extract any user:pwd */
@@ -165,12 +167,10 @@
         nc_uri->host = strdup(host);
     if(port && strlen(port) > 0)
         nc_uri->port = strdup(port);
-    if(file && strlen(file) > 0) {
-	/* Add back the leading / */
-        nc_uri->file = malloc(strlen(file)+2);
-	strcpy(nc_uri->file,"/");
-        strcat(nc_uri->file,file);
-    }
+    /* Add back the leading / */
+    nc_uri->file = malloc(strlen(file)+2);
+    strcpy(nc_uri->file,"/");
+    strcat(nc_uri->file,file);
     if(constraint && strlen(constraint) > 0)
         nc_uri->constraint = strdup(constraint);
     nc_urisetconstraints(nc_uri,constraint);
--- a/oc/ocuri.c
+++ b/oc/ocuri.c
@@ -115,7 +115,7 @@
     p += strlen(protocol);
 
     /* 5. skip // */
-    if(*p != '/' && *(p+1) != '/')
+    if(*p != '/' || *(p+1) != '/')
 	goto fail;
     p += 2;
 
@@ -123,6 +123,8 @@
     file = strchr(p,'/');
     if(file) {
 	*file++ = '\0'; /* warning: we just overwrote the leading / */
+    } else {
+        goto fail;
     }
 
     /* 7. extract any user:pwd */
@@ -165,12 +167,10 @@
         ocuri->host = strdup(host);
     if(port && strlen(port) > 0)
         ocuri->port = strdup(port);
-    if(file && strlen(file) > 0) {
-	/* Add back the leading / */
-        ocuri->file = malloc(strlen(file)+2);
-	strcpy(ocuri->file,"/");
-        strcat(ocuri->file,file);
-    }
+    /* Add back the leading / */
+    ocuri->file = malloc(strlen(file)+2);
+    strcpy(ocuri->file,"/");
+    strcat(ocuri->file,file);
     if(constraint && strlen(constraint) > 0)
         ocuri->constraint = strdup(constraint);
     ocurisetconstraints(ocuri,constraint);

Reply via email to