@@ -28,7 +28,7 @@ and whether it has checksums.
2828*/
2929
3030/* Define a local struct for convenience */
31- struct HDR {unsigned int flags ; unsigned int count ;};
31+ struct HDR {unsigned int flags ; unsigned int count ;};
3232
3333/* Forward */
3434static void * getheader (void * p , struct HDR * hdr , int hostlittleendian );
@@ -60,15 +60,18 @@ NCD4_dechunk(NCD4meta* metadata)
6060 q = metadata -> serial .rawdata ;
6161 if (memcmp (q ,"<?xml" ,strlen ("<?xml" ))== 0
6262 || memcmp (q ,"<Dataset" ,strlen ("<Dataset" ))== 0 ) {
63- if (metadata -> mode != NCD4_DMR )
64- return THROW (NC_EDMR );
65- /* setup as dmr only */
66- metadata -> serial .dmr = (char * )metadata -> serial .rawdata ; /* temp */
67- metadata -> serial .dmr [metadata -> serial .rawsize - 1 ] = '\0' ;
68- metadata -> serial .dmr = strdup ((char * )q );
69- if (metadata -> serial .dmr == NULL )
70- return THROW (NC_ENOMEM );
71- return THROW (NC_NOERR );
63+ if (metadata -> mode != NCD4_DMR )
64+ return THROW (NC_EDMR );
65+ /* setup as dmr only */
66+ metadata -> serial .dmr = (char * )metadata -> serial .rawdata ; /* temp */
67+ /* Avoid strdup since rawdata might contain nul chars */
68+ if ((metadata -> serial .dmr = malloc (metadata -> serial .rawsize + 1 )) == NULL )
69+ return THROW (NC_ENOMEM );
70+ memcpy (metadata -> serial .dmr ,metadata -> serial .rawdata ,metadata -> serial .rawsize );
71+ metadata -> serial .dmr [metadata -> serial .rawsize - 1 ] = '\0' ;
72+ /* Suppress nuls */
73+ (void )NCD4_elidenuls (metadata -> serial .dmr ,metadata -> serial .rawsize );
74+ return THROW (NC_NOERR );
7275 }
7376
7477 /* We must be processing a DAP mode packet */
@@ -82,7 +85,7 @@ NCD4_dechunk(NCD4meta* metadata)
8285 /* Get the DMR chunk header*/
8386 p = getheader (p ,& hdr ,metadata -> serial .hostlittleendian );
8487 if (hdr .count == 0 )
85- return THROW (NC_EDMR );
88+ return THROW (NC_EDMR );
8689 if (hdr .flags & ERR_CHUNK ) {
8790 return processerrchunk (metadata , (void * )p , hdr .count );
8891 }
@@ -91,31 +94,40 @@ NCD4_dechunk(NCD4meta* metadata)
9194 metadata -> localchecksumming = metadata -> serial .remotechecksumming ;
9295
9396 metadata -> serial .remotelittleendian = ((hdr .flags & LITTLE_ENDIAN_CHUNK ) ? 1 : 0 );
94- metadata -> serial .dmr = (char * )p ;
97+ /* Again, avoid strxxx operations on dmr */
98+ if ((metadata -> serial .dmr = malloc (hdr .count + 1 )) == NULL )
99+ return THROW (NC_ENOMEM );
100+ memcpy (metadata -> serial .dmr ,p ,hdr .count );
95101 metadata -> serial .dmr [hdr .count - 1 ] = '\0' ;
96- metadata -> serial .dmr = strdup (metadata -> serial .dmr );
97- if (metadata -> serial .dmr == NULL )
98- return THROW (NC_ENOMEM );
99- p += hdr .count ;
102+ /* Suppress nuls */
103+ (void )NCD4_elidenuls (metadata -> serial .dmr ,hdr .count );
100104
101105 if (hdr .flags & LAST_CHUNK )
102106 return THROW (NC_ENODATA );
103107 /* Read and compress the data chunks */
104- q = metadata -> serial .dap ;
108+ p = p + hdr .count ; /* point to data chunk header */
109+ /* Do a sanity check in case the server has shorted us with no data */
110+ if ((hdr .count + CHUNKHDRSIZE ) >= metadata -> serial .rawsize ) {
111+ /* Server only sent the DMR part */
112+ metadata -> serial .dapsize = 0 ;
113+ return THROW (NC_EDATADDS );
114+ }
115+ q = metadata -> serial .dap ;
105116 for (;;) {
106- p = getheader (p ,& hdr ,metadata -> serial .hostlittleendian );
107- if (hdr .flags & ERR_CHUNK ) {
117+ p = getheader (p ,& hdr ,metadata -> serial .hostlittleendian );
118+ if (hdr .flags & ERR_CHUNK ) {
108119 return processerrchunk (metadata , (void * )p , hdr .count );
109- }
110- /* data chunk; possibly last; possibly empty */
111- if (hdr .count > 0 ) {
112- d4memmove (q ,p ,hdr .count ); /* will overwrite the header */
113- p += hdr .count ;
114- q += hdr .count ;
115- }
116- if (hdr .flags & LAST_CHUNK ) break ;
120+ }
121+ /* data chunk; possibly last; possibly empty */
122+ if (hdr .count > 0 ) {
123+ d4memmove (q ,p ,hdr .count ); /* will overwrite the header */
124+ p += hdr .count ;
125+ q += hdr .count ;
126+ }
127+ if (hdr .flags & LAST_CHUNK ) break ;
117128 }
118129 metadata -> serial .dapsize = (size_t )DELTA (q ,metadata -> serial .dap );
130+
119131#ifdef D4DUMPDMR
120132 fprintf (stderr ,"%s\n" ,metadata -> serial .dmr );
121133 fflush (stderr );
@@ -169,8 +181,8 @@ getheader(void* p, struct HDR* hdr, int hostlittleendian)
169181 hyrax .count = * (unsigned int * )bytes ; /* get count */
170182 /* See which makes more sense */
171183 if (hyrax .flags <= ALL_CHUNK_FLAGS && hyrax .count >= 0 && hyrax .count < hdr -> count ) {
172- /* Use hyrax version */
173- * hdr = hyrax ;
184+ /* Use hyrax version */
185+ * hdr = hyrax ;
174186 }
175187#endif
176188 return p ;
@@ -187,17 +199,17 @@ NCD4_infermode(NCD4meta* meta)
187199 char * raw = meta -> serial .rawdata ;
188200
189201 if (size < 16 )
190- return THROW (NC_EDAP ); /* must have at least this to hold a hdr + partial dmr*/
202+ return THROW (NC_EDAP ); /* must have at least this to hold a hdr + partial dmr*/
191203 if (memcmp (raw ,"<?xml" ,strlen ("<?xml" ))== 0
192204 || memcmp (raw ,"<Dataset" ,strlen ("<Dataset" ))== 0 ) {
193- meta -> mode = NCD4_DMR ;
194- goto done ;
205+ meta -> mode = NCD4_DMR ;
206+ goto done ;
195207 }
196208 raw += 4 ; /* Pretend we have a DAP hdr */
197209 if (memcmp (raw ,"<?xml" ,strlen ("<?xml" ))== 0
198210 || memcmp (raw ,"<Dataset" ,strlen ("<Dataset" ))== 0 ) {
199- meta -> mode = NCD4_DAP ;
200- goto done ;
211+ meta -> mode = NCD4_DAP ;
212+ goto done ;
201213 }
202214 /* Default to DSR */
203215 meta -> mode = NCD4_DSR ;
0 commit comments