From d91ccdf54cfeb84ac25baf7c3dd252769bea89de Mon Sep 17 00:00:00 2001
From: Dennis Heimbigner <dmh@ucar.edu>
Date: Thu, 28 Jan 2016 22:18:51 -0700
Subject: [PATCH] Github issue: https://github.com/Unidata/netcdf-c/issues/206
 Re e-eupport VGQ-678069 It was noticed that an attribute value of "nan." was
 being treated as legal (it should be "nan"). The reason is that sscanf was
 not be checked to see that all the attribute value characters were being
 read. Solution is to verify that all characters were being consumed.

---
 libdap2/dapcvt.c       | 33 +++++++++++++++++----------------
 libdap2/env            | 14 +++++++++++---
 libdap2/ncd2dispatch.c |  8 +++++---
 3 files changed, 33 insertions(+), 22 deletions(-)

diff --git a/libdap2/dapcvt.c b/libdap2/dapcvt.c
index 394f30c95..b67ff846f 100644
--- a/libdap2/dapcvt.c
+++ b/libdap2/dapcvt.c
@@ -203,8 +203,9 @@ dapcvtattrval(nc_type etype, void* dst, NClist* src)
     char* dstmem = (char*)dst;
 
     for(i=0;i<nvalues;i++) {
-
 	char* s = (char*)nclistget(src,i);
+	size_t slen = strlen(s);
+        int nread = 0; /* # of chars read by sscanf */
 
 	ok = 0;
 	switch (etype) {
@@ -213,60 +214,60 @@ dapcvtattrval(nc_type etype, void* dst, NClist* src)
 		
 		unsigned char* p = (unsigned char*)dstmem;
 #ifdef _MSC_VER
-		ok = sscanf(s,"%hC",p);
+		ok = sscanf(s,"%hC%n",p,&nread);
 		_ASSERTE(_CrtCheckMemory());
 #else	
-		ok = sscanf(s,"%hhu",p);
+		ok = sscanf(s,"%hhu%n",p,&nread);
 #endif
 	    } break;
 	case NC_CHAR: {
 	    signed char* p = (signed char*)dstmem;
-	    ok = sscanf(s,"%c",p);
+	    ok = sscanf(s,"%c%n",p,&nread);
 	    } break;
 	case NC_SHORT: {
 	    short* p = (short*)dstmem;
-	    ok = sscanf(s,"%hd",p);
+	    ok = sscanf(s,"%hd%n",p,&nread);
 	    } break;
 	case NC_INT: {
 	    int* p = (int*)dstmem;
-	    ok = sscanf(s,"%d",p);
+	    ok = sscanf(s,"%d%n",p,&nread);
 	    } break;
 	case NC_FLOAT: {
 	    float* p = (float*)dstmem;
-	    ok = sscanf(s,"%g",p);
+	    ok = sscanf(s,"%g%n",p,&nread);
 	    } break;
 	case NC_DOUBLE: {
 	    double* p = (double*)dstmem;
-	    ok = sscanf(s,"%lg",p);
+	    ok = sscanf(s,"%lg%n",p,&nread);
 	    } break;
 	case NC_UBYTE: {
 	    unsigned char* p = (unsigned char*)dstmem;
 #ifdef _MSC_VER
-		ok = sscanf(s, "%hc", p);
+		ok = sscanf(s, "%hc%n", p,&nread);
 		_ASSERTE(_CrtCheckMemory());
 #else
-	    ok = sscanf(s,"%hhu",p);
+	    ok = sscanf(s,"%hhu%n",p,&nread);
 #endif
 		} break;
 	case NC_USHORT: {
 	    unsigned short* p = (unsigned short*)dstmem;
-	    ok = sscanf(s,"%hu",p);
+	    ok = sscanf(s,"%hu%n",p,&nread);
 	    } break;
 	case NC_UINT: {
 	    unsigned int* p = (unsigned int*)dstmem;
-	    ok = sscanf(s,"%u",p);
+	    ok = sscanf(s,"%u%n",p,&nread);
 	    } break;
 	case NC_INT64: {
 	    long long* p = (long long*)dstmem;
 #ifdef _MSC_VER
-		ok = sscanf(s, "%I64d", p);
+		ok = sscanf(s, "%I64d%n", p,&nread);
 #else
-		ok = sscanf(s,"%lld",p);
+		ok = sscanf(s,"%lld%n",p,&nread);
 #endif
 	} break;
 	case NC_UINT64: {
 	    unsigned long long* p = (unsigned long long*)dstmem;
-	    ok = sscanf(s,"%llu",p);
+	    ok = sscanf(s,"%llu%n",p,&nread);
 	    } break;
 	case NC_STRING: case NC_URL: {
 	    char** p = (char**)dstmem;
@@ -276,7 +277,7 @@ dapcvtattrval(nc_type etype, void* dst, NClist* src)
 	default:
    	    PANIC1("unexpected nc_type: %d",(int)etype);
 	}
-	if(ok != 1) {ncstat = NC_EINVAL; goto done;}
+	if(ok != 1 || nread != slen) {ncstat = NC_EINVAL; goto done;}
 	dstmem += memsize;
     }
 done:
diff --git a/libdap2/env b/libdap2/env
index 97d80303e..e4e59c319 100644
--- a/libdap2/env
+++ b/libdap2/env
@@ -1,12 +1,20 @@
-#TOP="/home/dmh/git/netcdf-c"
-TOP="/cygdrive/f/git/netcdf-c"
 
 alias xx="cd ..;make; cd libdap2"
 
 PARMS=""; ARGS=""; CON="" ; CE="";  OCON="" ; VAR=""; SHARP='#'
 alias q0=;alias qq=;alias qv=;alias q=;alias  qh=;alias qqh=;alias qall=;alias qv=;alias qo=;
 
-F="http://remotetest.unidata.ucar.edu/dts/test.01"
+F="https://eosdap.hdfgroup.org:8080/opendap/data/test/kent/ceres-converted/edition_4/CER_SSF1deg-Hour_Terra-MODIS_TestSuite_000000.200407D01.hdf"
+
+if test -e "/cygdrive/f/git/netcdf-c" ; then
+TOP="/cygdrive/f/git/netcdf-c"
+elif test -e "/cygdrive/d/git/netcdf-c" ; then
+TOP="/cygdrive/d/git/netcdf-c"
+elif test -e "/home/dmh/git/netcdf-c" ; then
+TOP="/home/dmh/git/netcdf-c"
+else
+echo "cannot locate ncdump"
+fi
 
 if test -f ./ncd ; then
 PROG=./ncd
diff --git a/libdap2/ncd2dispatch.c b/libdap2/ncd2dispatch.c
index 66c7bc979..0bb73dc8c 100644
--- a/libdap2/ncd2dispatch.c
+++ b/libdap2/ncd2dispatch.c
@@ -929,6 +929,7 @@ buildattribute(NCDAPCOMMON* dapcomm, NCattribute* att, nc_type vartype, int vari
 	else
 	    ncstat = nc_put_att_text(drno->substrate,varid,att->name,strlen(newstring),newstring);
 	free(newstring);
+        if(ncstat) goto done;
     } else {
 	nc_type atype;
 	unsigned int typesize;
@@ -955,13 +956,14 @@ buildattribute(NCDAPCOMMON* dapcomm, NCattribute* att, nc_type vartype, int vari
 #ifdef _MSC_VER
 	_ASSERTE(_CrtCheckMemory());
 #endif
+    if(ncstat) {nullfree(mem); goto done;}
     ncstat = nc_put_att(drno->substrate,varid,att->name,atype,nvalues,mem);
 #ifdef _MSC_VER
 	_ASSERTE(_CrtCheckMemory());
 #endif
-	if (mem != NULL)
-		free(mem);
-	}
+    if(ncstat) {nullfree(mem); goto done;}
+    }
+done:
     return THROW(ncstat);
 }