1 /******************************************************************************
2 *
3 *  NSSDC/CDF                      Validate internal records in a CDF V2.* file
4 *
5 *  Version 1.0, 15-Jul-08, Peort Systems.
6 *
7 *  Modification history:
8 *
9 *   V1.0  15-Jul-08, M Liu      Original version.
10 *
11 ******************************************************************************/
12 
13 #include "cdflib.h"
14 
15 /******************************************************************************
16 * Local macro definitions.
17 ******************************************************************************/
18 
19 #define CRE CDF_READ_ERROR
20 #define CV2C CORRUPTED_V2_CDF
21 
22 /******************************************************************************
23 * Local function prototypes.
24 ******************************************************************************/
25 
26 static CDFstatus QuitCDF PROTOARGs((char *why, int size, int num, void *value1, void *value2, Logical debug));
27 static CDFstatus ValidateCCR PROTOARGs((vFILE *fp, Int32 offset, Logical debug));
28 static CDFstatus ValidateCDR PROTOARGs((vFILE *fp, Int32 offset, Logical debug));
29 static CDFstatus ValidateGDR PROTOARGs((vFILE *fp, Int32 offset, Logical debug));
30 static CDFstatus ValidateVDR PROTOARGs((struct CDFstruct *CDF, vFILE *fp, Int32 offset, Logical zVar, Logical debug));
31 static CDFstatus ValidateVXR PROTOARGs((vFILE *fp, Int32 offset, Int32 lastRec, Logical debug));
32 static CDFstatus ValidateVVR PROTOARGs((vFILE *fp, Int32 offset, Logical debug));
33 static CDFstatus ValidateADR PROTOARGs((struct CDFstruct *CDF, vFILE *fp, Int32 offset, Logical debug));
34 static CDFstatus ValidateAEDR PROTOARGs((struct CDFstruct *CDF, vFILE *fp, Int32 offset, Int32 num, Int32 maxEntry, Logical zEntry, Logical debug));
35 static CDFstatus ValidateCPR PROTOARGs((vFILE *fp, Int32 offset, Logical debug));
36 static CDFstatus ValidateSPR PROTOARGs((vFILE *fp, Int32 offset, Logical debug));
37 static CDFstatus ValidateCVVR PROTOARGs((vFILE *fp, Int32 offset, Logical debug));
38 static CDFstatus ValidateUIR PROTOARGs((vFILE *fp, Int32 offset, Logical debug));
39 static CDFstatus ValidateAttributeLinks PROTOARGs((struct CDFstruct *CDF, vFILE *fp, Logical debug));
40 static CDFstatus ValidateAttributeEntryLink PROTOARGs((struct CDFstruct *CDF, vFILE *fp, Int32 num, Logical zEntry, Int32 AEDRhead, Int32 numEntries, Int32 maxEntry, Logical debug));
41 static CDFstatus ValidateVariableLinks PROTOARGs((struct CDFstruct *CDF, vFILE *fp, Logical zVar, Logical debug));
42 static CDFstatus ValidateVariableValueLinks PROTOARGs((struct CDFstruct *CDF, vFILE *fp, Int32 lastRec, Int32 headVXR, Logical debug));
43 static struct CDRstruct CDR;
44 static struct GDRstruct GDR;
45 static int rVars, zVars;
46 static int numAttrs;
47 
48 /******************************************************************************
49 * ValidateCDF.
50 *   Start to validate each internal record in a CDF file.
51 ******************************************************************************/
52 
ValidateCDF(struct CDFstruct * CDF,vFILE * CDFfp,Int32 offset,Int32 fileSize,Logical debug)53 STATICforIDL CDFstatus ValidateCDF (struct CDFstruct *CDF, vFILE *CDFfp,
54                                     Int32 offset, Int32 fileSize,
55                                     Logical debug)
56 {
57   Int32 recordSize;
58   Int32 recordType;
59   CDFstatus status;
60 
61   /****************************************************************************
62   * Read internal records from the beginning of the file until EOF (or illegal
63   * record) reached.
64   ****************************************************************************/
65   if (!SEEKv(CDFfp,offset,vSEEK_SET)) return CRE;
66   for (;;) {
67      /*************************************************************************
68      * Read record size.
69      *************************************************************************/
70      offset = V_tell (CDFfp);
71      if (offset >= fileSize) break;
72      if (!Read32(CDFfp,&recordSize)) return CRE;
73      if (recordSize < 1 || recordSize > fileSize)
74        return QuitCDF ("CDF: an invalid internal record size",
75                        4, 1, &recordSize, 0, debug);
76      /*************************************************************************
77      * Read record type.
78      *************************************************************************/
79      if (!Read32(CDFfp,&recordType)) return CRE;
80      /*************************************************************************
81      * Based on the record type...
82      *************************************************************************/
83      switch ((int)recordType) {
84         /**********************************************************************
85         * Compressed CDF Record (CCR).
86         **********************************************************************/
87         case CCR_: {
88           status = ValidateCCR (CDFfp, offset, debug);
89           if (status != CDF_OK) return status;
90           offset = offset + recordSize;
91           if (!SEEKv(CDFfp,offset,vSEEK_SET)) return CRE;
92 	  break;
93         }
94         /**********************************************************************
95         * CDF Descriptor Record (CDR).
96         **********************************************************************/
97         case CDR_: {
98           numAttrs = rVars = zVars = 0;
99           status = ValidateCDR (CDFfp, offset, debug);
100           if (status != CDF_OK) return status;
101 	  status = ValidateGDR (CDFfp, CDR.GDRoffset, debug);
102 	  if (status != CDF_OK) return status;
103           offset = offset + recordSize;
104           if (!SEEKv(CDFfp,offset,vSEEK_SET)) return CRE;
105 	  break;
106         }
107         /**********************************************************************
108         * Global Descriptor Record (GDR).
109         **********************************************************************/
110         case GDR_: {
111           offset = offset + recordSize;
112           if (!SEEKv(CDFfp,offset,vSEEK_SET)) return CRE;
113 	  break;
114         }
115         /**********************************************************************
116         * Attribute Descriptor Record (ADR).
117         **********************************************************************/
118         case ADR_: {
119           ++numAttrs;
120           offset = offset + recordSize;
121           if (!SEEKv(CDFfp,offset,vSEEK_SET)) return CRE;
122 	  break;
123         }
124         /**********************************************************************
125         * Attribute Entry Descriptor Record (AgrEDR or AzEDR).
126         **********************************************************************/
127         case AgrEDR_:
128         case AzEDR_: {
129           offset = offset + recordSize;
130           if (!SEEKv(CDFfp,offset,vSEEK_SET)) return CRE;
131 	  break;
132         }
133         /**********************************************************************
134         * Variable Descriptor Record (rVDR or zVDR).
135         **********************************************************************/
136         case rVDR_:
137         case zVDR_: {
138           Logical zVar = (recordType == zVDR_);
139           if (zVar)
140             ++zVars;
141           else
142             ++rVars;
143           offset = offset + recordSize;
144           if (!SEEKv(CDFfp,offset,vSEEK_SET)) return CRE;
145 	  break;
146         }
147         /**********************************************************************
148         * Variable indeX Record (VXR).
149         **********************************************************************/
150         case VXR_: {
151           offset = offset + recordSize;
152           if (!SEEKv(CDFfp,offset,vSEEK_SET)) return CRE;
153 	  break;
154         }
155         /**********************************************************************
156         * Variable Values Record (VVR).
157         **********************************************************************/
158         case VVR_: {
159           status = ValidateVVR (CDFfp, offset, debug);
160           if (recordSize < VVR_BASE_SIZE)
161             return QuitCDF ("CDF: record size is invalid ",
162                             4, 1, &recordSize, 0, debug);
163           offset = offset + recordSize;
164           if (!SEEKv(CDFfp,offset,vSEEK_SET)) return CRE;
165 	  break;
166         }
167         /**********************************************************************
168         * Compressed Variable Values Record (CVVR).
169         **********************************************************************/
170         case CVVR_: {
171           status = ValidateCVVR (CDFfp, offset, debug);
172           if (status != CDF_OK) return status;
173           offset = offset + recordSize;
174           if (!SEEKv(CDFfp,offset,vSEEK_SET)) return CRE;
175 	  break;
176         }
177         /**********************************************************************
178         * Compressed Parameters Record (CPR).
179         **********************************************************************/
180         case CPR_: {
181           offset = offset + recordSize;
182           if (!SEEKv(CDFfp,offset,vSEEK_SET)) return CRE;
183 	  break;
184         }
185         /**********************************************************************
186         * Sparseness Parameters Record (SPR).
187         **********************************************************************/
188         case SPR_: {
189 /*
190           status = ValidateSPR (CDFfp, offset, debug);
191           if (status != CDF_OK) return status;
192 */
193           offset = offset + recordSize;
194           if (!SEEKv(CDFfp,offset,vSEEK_SET)) return CRE;
195 	  break;
196         }
197         /**********************************************************************
198         * Unused internal record
199         **********************************************************************/
200         case UIR_: {
201           offset = offset + recordSize;
202           if (!SEEKv(CDFfp,offset,vSEEK_SET)) return CRE;
203 	  break;
204         }
205         /**********************************************************************
206         * Illegal record type.
207         **********************************************************************/
208         default: {
209 	    return QuitCDF ("CDF: an invalid internal record type",
210                             4, 1, &recordType, 0, debug);
211         }
212      }
213   }
214   /****************************************************************************
215   * Check attribute links and their attribute entries.
216   ****************************************************************************/
217   if (GDR.NumAttr != numAttrs)
218     return QuitCDF ("CDF: number of attributes does not match: ",
219                     4, 2, &GDR.NumAttr, &numAttrs, debug);
220   if (numAttrs > 0) {
221     status = ValidateAttributeLinks(CDF, CDFfp, debug);
222     if (status != CDF_OK) return status;
223   }
224   /****************************************************************************
225   * Check rVariable links and their data.
226   ****************************************************************************/
227   if (GDR.NrVars != rVars)
228     return QuitCDF ("CDF: number of rVariables does not match: ",
229                     4, 2, &GDR.NrVars, &rVars, debug);
230   if (rVars > 0) {
231     status = ValidateVariableLinks(CDF, CDFfp, FALSE, debug);
232     if (status != CDF_OK) return status;
233   }
234   /****************************************************************************
235   * Check zVariable links and their data.
236   ****************************************************************************/
237   if (GDR.NzVars != zVars)
238     return QuitCDF ("CDF: number of zVariables does not match: ",
239                     4, 2, &GDR.NzVars, &zVars, debug);
240   if (zVars > 0) {
241     status = ValidateVariableLinks(CDF, CDFfp, TRUE, debug);
242     if (status != CDF_OK) return status;
243   }
244   return CDF_OK;
245 }
246 
247 /******************************************************************************
248 * ValidateCDR.
249 ******************************************************************************/
250 
ValidateCDR(vFILE * fp,Int32 offset,Logical debug)251 CDFstatus ValidateCDR (vFILE *fp, Int32 offset, Logical debug)
252 {
253   Int32 actualEncoding;
254 /*
255   char copyRight[CDF_COPYRIGHT_LEN+1];
256 */
257   int i;
258   CDFstatus status;
259 
260   if (debug)
261     printf("  Checking CDR...@%ld\n", offset);
262   status = ReadCDR (fp, offset,
263                     CDR_RECORD, &CDR, NULL,
264                     CDR_NULL);
265   if (status != CDF_OK) return status;
266   if (CDR.RecordType != CDR_)
267     return QuitCDF ("CDF: record type is invalid ",
268                     4, 1, &(CDR.RecordType), 0, debug);
269   if (CDR.RecordSize < CDR_BASE_SIZE ||
270       (!PriorTo("2.5",CDR.Version,CDR.Release,CDR.Increment) &&
271        CDR.RecordSize > CDR_MAX_SIZE))
272     return QuitCDF ("CDF: record size is invalid ",
273                     4, 1, &(CDR.RecordSize), 0, debug);
274   if (CDR.GDRoffset < 1)
275     return QuitCDF ("CDF: offset to GDR is invalid ",
276                     4, 1, &(CDR.GDRoffset), 0, debug);
277   if (CDR.Version != 2)
278     return QuitCDF ("CDF: version number is invalid ",
279                     4, 1, &(CDR.Version), 0, debug);
280   if (!ValidEncoding(CDR.Encoding,&actualEncoding))
281     return QuitCDF ("CDF: encoding is invalid ",
282                     4, 1, &(CDR.Encoding), 0, debug);
283 /*
284   for (i = 0; i < strlen(copyRight); ++i)
285     if (!Printable(copyRight[i]))
286       return QuitCDF ("CDF: copyright is invalid ",
287                       0, copyRight), 0, debug);
288 */
289   return CDF_OK;
290 }
291 
292 /******************************************************************************
293 * ValidateGDR.
294 ******************************************************************************/
295 
ValidateGDR(vFILE * fp,Int32 offset,Logical debug)296 CDFstatus ValidateGDR (vFILE *fp, Int32 offset, Logical debug)
297 {
298   int i;
299   CDFstatus status;
300 
301   if (debug)
302     printf("  Checking GDR...@%ld\n", offset);
303   status = ReadGDR (fp, offset,
304                     GDR_RECORD, &GDR,
305                     GDR_NULL);
306   if (status != CDF_OK) return status;
307   if (GDR.RecordType != GDR_)
308     return QuitCDF ("CDF: record type is invalid ",
309                     4, 1, &(GDR.RecordType), 0, debug);
310   if (GDR.RecordSize < GDR_BASE_SIZE ||
311       GDR.RecordSize > GDR_MAX_SIZE)
312     return QuitCDF ("CDF: record size is invalid ",
313                     4, 1, &(GDR.RecordSize), 0, debug);
314   if (GDR.NrVars < 0 || (GDR.NrVars > 0 && GDR.rVDRhead < 1))
315     return QuitCDF ("CDF: NrVars or their link is invalid ",
316                     4, 1, &(GDR.NrVars), 0, debug);
317   if (GDR.NumAttr < 0 || (GDR.NumAttr > 0 && GDR.ADRhead < 1))
318     return QuitCDF ("CDF: attribute numbers or their link is invalid ",
319                     4, 1, &(GDR.NumAttr), 0, debug);
320   if (GDR.rMaxRec < -1)
321     return QuitCDF ("CDF: max rVars record is invalid ",
322                     4, 1, &(GDR.rMaxRec), 0, debug);
323   if (GDR.rNumDims < 0 ||
324       GDR.rNumDims > CDF_MAX_DIMS)
325     return QuitCDF ("CDF: number of dimensions for rVars is invalid ",
326                     4, 1, &(GDR.rNumDims), 0, debug);
327   if (GDR.NzVars < 0 || (GDR.NzVars > 0 && GDR.zVDRhead < 1))
328     return QuitCDF ("CDF: NzVars or their link is invalid ",
329                     4, 1, &(GDR.NzVars), 0, debug);
330   if (GDR.UIRhead < 0)
331     return QuitCDF ("CDF: offset to UIR is invalid ",
332                     4, 1, &(GDR.UIRhead), 0, debug);
333   for (i = 0; i < (int)GDR.rNumDims; ++i)
334     if (GDR.rDimSizes[i] < 1)
335     return QuitCDF ("CDF: dimensional size is invalid ",
336                     4, 1, &(GDR.rDimSizes[i]), 0, debug);
337   return CDF_OK;
338 }
339 
340 /******************************************************************************
341 * ValidateADR.
342 ******************************************************************************/
343 
ValidateADR(struct CDFstruct * CDF,vFILE * fp,Int32 offset,Logical debug)344 CDFstatus ValidateADR (struct CDFstruct *CDF, vFILE *fp, Int32 offset,
345                        Logical debug)
346 {
347   struct ADRstruct ADR;
348   CDFstatus status;
349 
350   if (debug)
351     printf("  Checking ADR...@%ld\n", offset);
352   status = ReadADR (fp, offset,
353                     ADR_RECORD, &ADR,
354                     ADR_NULL);
355   if (status != CDF_OK) return status;
356   if (ADR.RecordType != ADR_)
357     return QuitCDF ("CDF: record type is invalid ",
358                     4, 1, &(ADR.RecordType), 0, debug);
359 
360   if (ADR.RecordSize < ADR_BASE_SIZE ||
361       ADR.RecordSize > ADR_MAX_SIZE)
362     return QuitCDF ("CDF: record size is invalid ",
363                     4, 1, &(ADR.RecordSize), 0, debug);
364   if (ADR.ADRnext < 0 || ((ADR.Num < (GDR.NumAttr-1))  && ADR.ADRnext == 0))
365     return QuitCDF ("CDF: offset to next ADR is invalid ",
366                     4, 1, &(ADR.ADRnext), 0, debug);
367   if (ADR.AgrEDRhead < 0 || (ADR.NgrEntries > 0 && ADR.AgrEDRhead == 0))
368     return QuitCDF ("CDF: record size is invalid ",
369                     4, 1, &(ADR.AgrEDRhead), 0, debug);
370 /*
371   if ((ADR.Scope == GLOBAL_SCOPE) && (ADR.NzEntries > 0))
372     return QuitCDF ("CDF: attribute zEntries exist for a global attribute ",
373                     4, 1, &(ADR.NzEntries), 0, debug);
374 */
375   if (!ValidAttrScope(ADR.Scope))
376     return QuitCDF ("CDF: scope is invalid ",
377                     4, 1, &(ADR.Scope), 0, debug);
378   if (ADR.Num < 0 || ADR.Num > GDR.NumAttr)
379     return QuitCDF ("CDF: attribute number is invalid ",
380                     4, 2, &(ADR.Num), &(GDR.NumAttr), debug);
381   if (ADR.NgrEntries < 0)
382     return QuitCDF ("CDF: number of g/rEntries is invalid ",
383                     4, 1, &(ADR.NgrEntries), 0, debug);
384 /*
385   if ((ADR.Scope == VARIABLE_SCOPE) && (ADR.NgrEntries > CDF->NrVars))
386     return QuitCDF ("CDF: number of rEntries is invalid ",
387                     4, 1, &(ADR.NgrEntries), 0, debug);
388 */
389   if (ADR.MAXgrEntry < -1)
390     return QuitCDF ("CDF: max g/rEntry is invalid ",
391                     4, 1, &(ADR.MAXgrEntry), 0, debug);
392   if ((ADR.Scope == VARIABLE_SCOPE) && (ADR.MAXgrEntry < (ADR.NgrEntries-1)))
393     return QuitCDF ("CDF: max rEntry is invalid ",
394                     4, 2, &(ADR.MAXgrEntry), &(ADR.NgrEntries), debug);
395   if (ADR.AzEDRhead < 0 || (ADR.NzEntries > 0 && ADR.AzEDRhead == 0))
396     return QuitCDF ("CD2: offset to next AzEDR is invalid ",
397                     4, 1, &(ADR.AzEDRhead), 0, debug);
398 /*
399   if (ADR.NzEntries < 0 || ((ADR.Scope == VARIABLE_SCOPE) &&
400                             (ADR.NzEntries > CDF->NzVars)))
401     return QuitCDF ("CDF: number of zEntries is invalid ",
402                     4, 2, &(ADR.NzEntries), &(CDF->NzVars), debug);
403   if (ADR.MAXzEntry < -1 || ((ADR.Scope == VARIABLE_SCOPE) &&
404                              (ADR.MAXzEntry > CDF->NzVars)))
405     return QuitCDF ("CDF: max zEntry is invalid ",
406                     4, 2, &(ADR.MAXzEntry), &(CDF->NzVars), debug);
407 */
408   if ((ADR.Scope == VARIABLE_SCOPE) && (ADR.MAXzEntry < (ADR.NzEntries-1)))
409     return QuitCDF ("CDF: max zEntry is invalid ",
410                     4, 2, &(ADR.MAXzEntry), &(ADR.NzEntries), debug);
411   if (!ValidAttrName(ADR.Name))
412     return QuitCDF ("CDF: attribute name is invalid ",
413                     0, 1, ADR.Name, 0, debug);
414   return CDF_OK;
415 }
416 
417 /******************************************************************************
418 * ValidateAEDR/AzEDR.
419 ******************************************************************************/
420 
ValidateAEDR(struct CDFstruct * CDF,vFILE * fp,Int32 offset,Int32 num,Int32 maxEntry,Logical zEntry,Logical debug)421 CDFstatus ValidateAEDR (struct CDFstruct *CDF, vFILE *fp, Int32 offset,
422                         Int32 num, Int32 maxEntry, Logical zEntry,
423                         Logical debug)
424 {
425   struct AEDRstruct AEDR;
426   size_t nBytes;
427   CDFstatus status;
428 
429   if (debug)
430     printf("  Checking AEDR...@%ld\n", offset);
431   status = ReadAEDR (fp, offset,
432                      AEDR_RECORD, &AEDR, NULL,
433                      AEDR_NULL);
434   if (status != CDF_OK) return status;
435   if ((!zEntry && AEDR.RecordType != AgrEDR_) ||
436       (zEntry && AEDR.RecordType != AzEDR_))
437     return QuitCDF ("CDF: record type is invalid ",
438                     4, 1, &(AEDR.RecordType), 0, debug);
439   if (AEDR.RecordSize < AEDR_BASE_SIZE)
440     return QuitCDF ("CDF: record size is invalid ",
441                     4, 1, &(AEDR.RecordSize), 0, debug);
442   if (AEDR.AEDRnext < 0)
443     return QuitCDF ("CDF: offset to next AEDR is invalid ",
444                     4, 1, &(AEDR.AEDRnext), 0, debug);
445 /*  Check for "AEDR.AttrNum != num" is not included as some CDFs fail this
446     check. Don't know why.... */
447 /*  if (AEDR.AttrNum < 0 || AEDR.AttrNum > GDR.NumAttr || AEDR.AttrNum != num)  */
448 /*
449   if (AEDR.AttrNum < 0 || AEDR.AttrNum > GDR.NumAttr)
450     return QuitCDF ("CDF: attribute number is invalid ",
451                     4, 2, &(AEDR.AttrNum), &(GDR.NumAttr), debug);
452 */
453   if (!ValidDataType(AEDR.DataType))
454     return QuitCDF ("CDF: data type is invalid ",
455                     4, 1, &(AEDR.DataType), 0, debug);
456   if (AEDR.Num < 0 || AEDR.Num > maxEntry)
457     return QuitCDF ("CDF: entry number is invalid ",
458                     4, 2, &(AEDR.Num), &maxEntry, debug);
459   if (AEDR.AEDRnext < 0)
460     return QuitCDF ("CDF: next AEDR offset is invalid : ",
461                     4, 1, &(AEDR.AEDRnext), 0, debug);
462 /*
463   if (zEntry && AEDR.EntryNum > GDR->NzVars)
464     return QuitCDF ("CDF: entry number is invalid ",
465                     4, 2, &(AEDR.Num), &(GDR->NzVars), debug);
466 */
467   if (AEDR.NumElems < 1 ||
468       (STRINGdataType(AEDR.DataType) &&
469        AEDR.NumElems > (AEDR.RecordSize - AEDR_VALUE_OFFSET)))
470     return QuitCDF ("CDF: number of elements is invalid ",
471                     4, 1, &(AEDR.NumElems), 0, debug);
472   nBytes = (size_t) (CDFelemSize(AEDR.DataType) * AEDR.NumElems);
473   if (nBytes < 1 ||
474       nBytes > (AEDR.RecordSize - AEDR_VALUE_OFFSET))
475     return QuitCDF ("CDF: entry value size is invalid ",
476                     4, 1, &nBytes, 0, debug);
477   if (AEDR.RecordSize > (AEDR_MAX_SIZE + nBytes))
478     return QuitCDF ("CDF: record size is invalid ",
479                     4, 1, &(AEDR.RecordSize), 0, debug);
480   return CDF_OK;
481 }
482 
483 /******************************************************************************
484 * ValidateVDR/zVDR.
485 ******************************************************************************/
486 
ValidateVDR(struct CDFstruct * CDF,vFILE * fp,Int32 offset,Logical zVar,Logical debug)487 CDFstatus ValidateVDR (struct CDFstruct *CDF, vFILE *fp, Int32 offset,
488 		       Logical zVar, Logical debug)
489 {
490   struct VDRstruct VDR;
491   void *padValue;
492   Int32 nDims, numVars;
493   int ix;
494   CDFstatus status;
495   size_t nBytes;
496 
497   if (debug)
498     printf("  Checking VDR...@%ld\n", offset);
499   status = ReadVDR (CDF, fp, offset, zVar,
500                     VDR_RECORD, &VDR, NULL,
501                     VDR_NULL);
502   if (status != CDF_OK) return status;
503   if ((!zVar && VDR.RecordType != rVDR_) || (zVar && VDR.RecordType != zVDR_))
504     return QuitCDF ("CDF: record type is invalid ",
505                     4, 1, &(VDR.RecordType), 0, debug);
506   if (VDR.RecordSize < (zVar ? zVDR_BASE_SIZE : rVDR_BASE_SIZE))
507     return QuitCDF ("CDF: record size is invalid ",
508                     4, 1, &(VDR.RecordSize), 0, debug);
509   if (!ValidDataType(VDR.DataType))
510     return QuitCDF ("CDF: data type is invalid ",
511                     4, 1, &(VDR.DataType), 0, debug);
512   if (VDR.MaxRec < -1)
513     return QuitCDF ("CDF: max record is invalid ",
514                     4, 1, &(VDR.MaxRec), 0, debug);
515   if (VDR.NumElems < 1 || (!STRINGdataType(VDR.DataType) && VDR.NumElems != 1))
516     return QuitCDF ("CDF: number of elements is invalid ",
517                     4, 1, &(VDR.NumElems), 0, debug);
518   if (zVar) numVars = CDF->NzVars;
519   else numVars = CDF->NrVars;
520   if (VDR.Num < 0 || VDR.Num > numVars)
521     return QuitCDF ("CDF: variable number is invalid ",
522                     4, 2, &(VDR.Num), &numVars, debug);
523   if ((VDR.Num < (numVars-1)) && VDR.VDRnext < 1)
524     return QuitCDF ("CDF: offset to next VDR is invalid ",
525                     4, 1, &(VDR.VDRnext), 0, debug);
526   if (VARcompressionBITset(VDR.Flags) && VDR.CPRorSPRoffset <= (int) NO_OFFSET)
527     return QuitCDF ("CDF: offset to CPRorSPR is invalid ",
528                     4, 1, &(VDR.CPRorSPRoffset), 0, debug);
529   if (VDR.blockingFactor < 0)
530     return QuitCDF ("CDF: blocking factor is invalid ",
531                     4, 1, &(VDR.blockingFactor), 0, debug);
532   if (!ValidVarName(VDR.Name))
533     return QuitCDF ("CDF: variable name is invalid ",
534                     0, 1, VDR.Name, 0, debug);
535   if (zVar) {
536     if (VDR.zNumDims < 0 || VDR.zNumDims > CDF_MAX_DIMS)
537     return QuitCDF ("CDF: number of dimensions is invalid ",
538                     4, 1, &(VDR.zNumDims), 0, debug);
539     for (ix = 0; ix < (int)VDR.zNumDims; ++ix)
540       if (VDR.zDimSizes[ix] < 1)
541     return QuitCDF ("CDF: dimensional size is invalid ",
542                     4, 1, &(VDR.zDimSizes[ix]), 0, debug);
543   }
544   nBytes = (size_t) (CDFelemSize(VDR.DataType)*VDR.NumElems);
545   if (nBytes < 1)
546     return QuitCDF ("CDF: pad value size is invalid ",
547                     4, 1, &nBytes, 0, debug);
548   if (VDR.RecordSize > ((zVar ? zVDR_MAX_SIZE : rVDR_MAX_SIZE) + nBytes +
549                          (CDF->wastedSpace ? VDR_WASTED_SIZE : 0)))
550     return QuitCDF ("CDF: record size is invalid ",
551                     4, 1, &(VDR.RecordSize), 0, debug);
552   return CDF_OK;
553 }
554 
555 /******************************************************************************
556 * ValidateVXR.
557 ******************************************************************************/
558 
ValidateVXR(vFILE * fp,Int32 offset,Int32 lastRec,Logical debug)559 CDFstatus ValidateVXR (vFILE *fp, Int32 offset, Int32 lastRec, Logical debug)
560 {
561   struct VXRstruct VXR;
562   int i;
563   Int32 irType;
564   CDFstatus status;
565 
566   if (debug)
567     printf("  Checking VXR...@%ld\n", offset);
568   status = ReadVXR (fp, offset,
569                     VXR_RECORD, &VXR,
570                     VXR_NULL);
571   if (status != CDF_OK) return status;
572   if (VXR.RecordType != VXR_)
573     return QuitCDF ("CDF: record type is invalid ",
574                     4, 1, &(VXR.RecordType), 0, debug);
575   if (VXR.RecordSize != (VXR_FIRSTREC_OFFSET + 12 * VXR.Nentries))
576     return QuitCDF ("CDF: record size is invalid ",
577                     4, 1, &(VXR.RecordSize), 0, debug);
578   if (VXR.Nentries < 0 || VXR.Nentries > MAX_VXR_ENTRIES)
579     return QuitCDF ("CDF: number of entries is invalid ",
580                     4, 1, &(VXR.Nentries), 0, debug);
581   if (VXR.NusedEntries < 0 || VXR.NusedEntries > VXR.Nentries)
582     return QuitCDF ("CDF: number of used entries is invalid ",
583                     4, 2, &(VXR.NusedEntries), &(VXR.Nentries), debug);
584   if (VXR.VXRnext > 0) {
585     if (VXR.Last[VXR.NusedEntries-1] > lastRec)
586       return QuitCDF ("CDF: a variable last record does not match in a Variable Index Record: ",
587                       4, 2, &(VXR.Last[VXR.NusedEntries-1]), &lastRec, debug);
588     status = ValidateVXR (fp, VXR.VXRnext, lastRec, debug);
589     if (status != CDF_OK) return status;
590   } else if (VXR.VXRnext < 0) {
591       return QuitCDF ("CDF: a link offset to next record is negative in a Variable Index Record: ",
592                       4, 1, &(VXR.VXRnext), 0, debug);
593   }
594 
595   for (i = 0; i < VXR.NusedEntries; ++i) {
596     if (VXR.First[i] < 0 || VXR.Last[i] < 0 || VXR.First[i] > VXR.Last[i])
597       return QuitCDF ("CDF: entry value for first/last is invalid ",
598                       4, 2, &(VXR.First[i]), &(VXR.Last[i]), debug);
599     if (VXR.Offset[i] < 1)
600       return QuitCDF ("CDF: entry value for offset is invalid ",
601                       4, 1, &(VXR.Offset[i]), 0, debug);
602 
603     status = ReadIrType (fp, VXR.Offset[i], &irType);
604     if (status != CDF_OK) return status;
605     if (irType != VXR_ && irType != VVR_ && irType != CVVR_)
606       return QuitCDF ("CDF: entry value for offset is invalid ",
607                       4, 1, &(VXR.Offset[i]), 0, debug);
608     if (irType == VXR_ && VXR.Offset[i] != offset) {
609       status = ValidateVXR (fp, VXR.Offset[i], lastRec, debug);
610       if (status != CDF_OK) return status;
611     }
612   }
613   return CDF_OK;
614 }
615 
616 /******************************************************************************
617 * ValidateVVR.
618 ******************************************************************************/
619 
ValidateVVR(vFILE * fp,Int32 offset,Logical debug)620 CDFstatus ValidateVVR (vFILE *fp, Int32 offset, Logical debug)
621 {
622   struct VVRstruct VVR;
623   CDFstatus status;
624 
625   if (debug)
626     printf("  Checking VVR...@%ld\n", offset);
627   status = ReadVVR (fp, offset,
628                     VVR_RECORDx, &VVR,
629                     VVR_NULL);
630   if (status != CDF_OK) return status;
631   if (VVR.RecordType != VVR_)
632     return QuitCDF ("CDF: record type is invalid ",
633                     4, 1, &(VVR.RecordType), 0, debug);
634   if (VVR.RecordSize < VVR_BASE_SIZE)
635     return QuitCDF ("CDF: record size is invalid for Variable Value Record",
636                     4, 1, &(VVR.RecordSize), 0, debug);
637   return CDF_OK;
638 }
639 
640 /******************************************************************************
641 * ValidateUIR.
642 ******************************************************************************/
643 
ValidateUIR(vFILE * fp,Int32 offset,Logical debug)644 CDFstatus ValidateUIR (vFILE *fp, Int32 offset, Logical debug)
645 {
646   struct UIRstruct UIR;
647   CDFstatus status;
648 
649   if (debug)
650     printf("  Checking UIR...@%ld\n", offset);
651   status = ReadUIR (fp, offset,
652                     UIR_RECORD, &UIR,
653                     UIR_NULL);
654   if (status != CDF_OK) return status;
655   if (UIR.RecordType != UIR_)
656     return QuitCDF ("CDF: record type is invalid ",
657                     4, 1, &(UIR.RecordType), 0, debug);
658   if (UIR.RecordSize < UIR_BASE_SIZE)
659     return QuitCDF ("CDF: record size is invalid for Unused Internal Record",
660                     4, 1, &(UIR.RecordSize), 0, debug);
661   if (UIR.NextUIR < 0)
662     return QuitCDF ("CDF: offset to next UIR is invalid for Unused Internal Record",
663                     4, 1, &(UIR.NextUIR), 0, debug);
664   if (UIR.PrevUIR < 0)
665     return QuitCDF ("CDF: offset to previous UIR is invalid for Unused Internal Record",
666                     4, 1, &(UIR.PrevUIR), 0, debug);
667   return CDF_OK;
668 }
669 
670 /******************************************************************************
671 * ValidateCCR.
672 ******************************************************************************/
673 
ValidateCCR(vFILE * fp,Int32 offset,Logical debug)674 CDFstatus ValidateCCR (vFILE *fp, Int32 offset, Logical debug)
675 {
676   struct CCRstruct CCR;
677   CDFstatus status;
678 
679   if (debug)
680     printf("  Checking CCR...@%ld\n", offset);
681   status = ReadCCR (fp, offset,
682                     CCR_RECORD, &CCR,
683                     CCR_NULL);
684   if (status != CDF_OK) return status;
685   if (CCR.RecordType != CCR_)
686     return QuitCDF ("CDF: record type is invalid ",
687                     4, 1, &(CCR.RecordType), 0, debug);
688   if (CCR.RecordSize < CCR_BASE_SIZE)
689     return QuitCDF ("CDF: record size is invalid ",
690                     4, 1, &(CCR.RecordSize), 0, debug);
691   if (CCR.uSize < 0)
692     return QuitCDF ("CDF: uncompressed file size is invalid ",
693                     4, 1, &(CCR.uSize), 0, debug);
694   if (CCR.CPRoffset < 0)
695     return QuitCDF ("CDF: offset to SPR is invalid ",
696                     4, 1, &(CCR.CPRoffset), 0, debug);
697   return CDF_OK;
698 }
699 
700 /******************************************************************************
701 * ValidateCPR.
702 ******************************************************************************/
703 
ValidateCPR(vFILE * fp,Int32 offset,Logical debug)704 CDFstatus ValidateCPR (vFILE *fp, Int32 offset, Logical debug)
705 {
706   struct CPRstruct CPR;
707   int i;
708   CDFstatus status;
709   long cType, cParms[1];
710 
711   if (debug)
712     printf("  Checking CPR...@%ld\n", offset);
713   status = ReadCPR (fp, offset,
714                     CPR_RECORD, &CPR,
715                     CPR_NULL);
716   if (status != CDF_OK) return status;
717   if (CPR.RecordType != CPR_)
718     return QuitCDF ("CDF: record type is invalid ",
719                     4, 1, &(CPR.RecordType), 0, debug);
720   if (CPR.RecordSize != (CPR_BASE_SIZE + CPR.pCount * sizeof(Int32)))
721     return QuitCDF ("CDF: reocrd size is invalid ",
722                     4, 1, &(CPR.RecordSize), 0, debug);
723   if (CPR.pCount != 1)
724     return QuitCDF ("CDF: compression parameter count is invalid ",
725                     4, 1, &(CPR.pCount), 0, debug);
726   cType = (long) CPR.cType;
727   cParms[0] = (long) CPR.cParms[0];
728   if (ValidateCompression(cType, cParms) != CDF_OK)
729     return QuitCDF ("CDF: compression parameter is invalid ",
730                     4, 1, &(CPR.cType), 0, debug);
731   return CDF_OK;
732 }
733 
734 /******************************************************************************
735 * ValidateSPR.
736 ******************************************************************************/
737 
ValidateSPR(vFILE * fp,Int32 offset,Logical debug)738 CDFstatus ValidateSPR (vFILE *fp, Int32 offset, Logical debug)
739 {
740   struct SPRstruct SPR;
741   CDFstatus status;
742 
743   if (debug)
744     printf("  Checking SPR...@%ld\n", offset);
745   status = ReadSPR (fp, offset,
746                     SPR_RECORD, &SPR,
747                     SPR_NULL);
748   if (status != CDF_OK) return status;
749   if (SPR.RecordType != SPR_)
750     return QuitCDF ("CDF: record type is invalid ",
751                     4, 1, &(SPR.RecordType), 0, debug);
752   if (SPR.RecordSize != (SPR_BASE_SIZE + SPR.pCount * sizeof(Int32)))
753     return QuitCDF ("CDF: record size is invalid ",
754                     4, 1, &(SPR.RecordSize), 0, debug);
755   if (SPR.pCount < 1 || SPR.pCount > CDF_MAX_PARMS)
756     return QuitCDF ("CDF: sparseness parameter count is invalid ",
757                     4, 1, &(SPR.pCount), 0, debug);
758   return CDF_OK;
759 }
760 
761 /******************************************************************************
762 * ValidateCVVR.
763 ******************************************************************************/
764 
ValidateCVVR(vFILE * fp,Int32 offset,Logical debug)765 CDFstatus ValidateCVVR (vFILE *fp, Int32 offset, Logical debug)
766 {
767   struct CVVRstruct CVVR;
768   CDFstatus status;
769 
770   if (debug)
771     printf("  Checking CVVR...@%ld\n", offset);
772   status = ReadCVVR (fp, offset,
773                      CVVR_RECORDx, &CVVR,
774                      CVVR_NULL);
775   if (status != CDF_OK) return status;
776   if (CVVR.RecordSize < CVVR_BASE_SIZE)
777     return QuitCDF ("CDF: record size is invalid ",
778                     4, 1, &(CVVR.RecordSize), 0, debug);
779   if (CVVR.cSize < 0)
780     return QuitCDF ("CDF: uncompressed records size is invalid ",
781                     4, 1, &(CVVR.cSize), 0, debug);
782   return CDF_OK;
783 }
784 
785 /******************************************************************************
786 * ValidateAttributeLinks.
787 ******************************************************************************/
788 
ValidateAttributeLinks(struct CDFstruct * CDF,vFILE * fp,Logical debug)789 CDFstatus ValidateAttributeLinks (struct CDFstruct *CDF, vFILE *fp,
790                                   Logical debug)
791 {
792   CDFstatus status;
793   Int32 offset, nextADR, AgrEDRhead, AzEDRhead;
794   Int32 num, numgrEntries, maxgrEntry, numzEntries, maxzEntry, scope;
795   int ix, *visit;
796 
797   visit = (int *) malloc(GDR.NumAttr * sizeof(Int32));
798   for (ix = 0; ix < GDR.NumAttr; ++ix)
799     visit[ix] = 0;
800   offset = GDR.ADRhead;
801   for (ix = 0; ix < GDR.NumAttr; ++ix) {
802     status = ValidateADR (CDF, fp, offset, debug);
803     if (status != CDF_OK) {
804       free (visit);
805       return status;
806     }
807     status = ReadADR (fp, offset,
808                       ADR_NUM, &num,
809                       ADR_ADRNEXT, &nextADR,
810                       ADR_AgrEDRHEAD, &AgrEDRhead,
811                       ADR_NgrENTRIES, &numgrEntries,
812                       ADR_MAXgrENTRY, &maxgrEntry,
813                       ADR_AzEDRHEAD, &AzEDRhead,
814                       ADR_NzENTRIES, &numzEntries,
815                       ADR_MAXzENTRY, &maxzEntry,
816                       ADR_NULL);
817     if (numgrEntries > 0)
818       status = ValidateAttributeEntryLink (CDF, fp, num, FALSE, AgrEDRhead,
819                                            numgrEntries, maxgrEntry, debug);
820     if (status != CDF_OK) {
821       free (visit);
822       return status;
823     }
824     if (numzEntries > 0)
825       status = ValidateAttributeEntryLink (CDF, fp, num, TRUE, AzEDRhead,
826                                            numzEntries, maxzEntry, debug);
827     if (status != CDF_OK) {
828       free (visit);
829       return status;
830     }
831     visit[num] = 1;
832     offset = nextADR;
833   }
834   for (ix = 0; ix < GDR.NumAttr; ++ix) {
835     if (visit[ix] == 0) {
836       free (visit);
837       return QuitCDF ("CDF: an attribute unreachable in the attribute link: ",
838                        4, 1, &ix, 0, debug);
839     }
840   }
841   free (visit);
842   return CDF_OK;
843 }
844 
845 /******************************************************************************
846 * ValidateAttributeEntryLink.
847 ******************************************************************************/
848 
ValidateAttributeEntryLink(struct CDFstruct * CDF,vFILE * fp,Int32 num,Logical zEntry,Int32 EDRhead,Int32 numEntries,Int32 maxEntry,Logical debug)849 CDFstatus ValidateAttributeEntryLink (struct CDFstruct *CDF, vFILE *fp,
850                                       Int32 num, Logical zEntry, Int32 EDRhead,
851                                       Int32 numEntries, Int32 maxEntry,
852                                       Logical debug)
853 {
854   CDFstatus status;
855   Int32 offset, nextAEDR;
856   Int32 entryNum, lastNum, *visits;
857   int ix, iy;
858 
859   offset = EDRhead;
860   lastNum = 0;
861   visits = (Int32 *) cdf_AllocateMemory (numEntries * sizeof(Int32), NULL);
862   if (visits == NULL) return BAD_MALLOC;
863   for (ix = 0; ix < numEntries; ++ix)
864     visits[ix] = 0;
865   ix = 0;
866   while (offset != 0) {
867     status = ValidateAEDR (CDF, fp, offset, num, maxEntry, zEntry, debug);
868     if (status != CDF_OK) {
869       cdf_FreeMemory (visits, NULL);
870       return status;
871     }
872     status = ReadAEDR (fp, offset,
873                        AEDR_NUM, &entryNum,
874                        AEDR_AEDRNEXT, &nextAEDR,
875                        AEDR_NULL);
876     if (ix > 0) {
877       for (iy = 0; iy < ix; ++iy) {
878         if (visits[iy] == entryNum) {
879           cdf_FreeMemory (visits, NULL);
880           return QuitCDF ("CDF: entry number is repeating in an attribute entry link: ",
881                           4, 1, &entryNum, 0, debug);
882         }
883       }
884     }
885     if (ix == (int) numEntries) {
886       cdf_FreeMemory (visits, NULL);
887       return QuitCDF ("CDF: number of entries is more than maximum in an attribute entry link: ",
888                       4, 1, &ix, 0, debug);
889     }
890     visits[ix] = entryNum;
891     ++ix;
892     if (lastNum < entryNum) lastNum = entryNum;
893     offset = nextAEDR;
894   }
895   if (lastNum != maxEntry) {
896     cdf_FreeMemory (visits, NULL);
897     return QuitCDF ("CDF: last entry number is not the maximum entry number in  an attribute entry link: ",
898                     4, 2, &lastNum, &maxEntry, debug);
899   }
900   cdf_FreeMemory (visits, NULL);
901   return CDF_OK;
902 }
903 
904 /******************************************************************************
905 * ValidateVariableLinks.
906 ******************************************************************************/
907 
ValidateVariableLinks(struct CDFstruct * CDF,vFILE * fp,Logical zVar,Logical debug)908 CDFstatus ValidateVariableLinks (struct CDFstruct *CDF, vFILE *fp,
909                                  Logical zVar, Logical debug)
910 {
911   CDFstatus status;
912   Int32 offset, headVXR, tailVXR, nextVDR, cprOffset;
913   Int32 num, lastRec, flags;
914   int ix, numVars, *visit;
915 
916   numVars = (zVar ? GDR.NzVars : GDR.NrVars);
917   visit = (int *) cdf_AllocateMemory (numVars * sizeof(Int32), NULL);
918   if (visit == NULL) return BAD_MALLOC;
919   for (ix = 0; ix < numVars; ++ix)
920     visit[ix] = 0;
921   offset = (zVar ? GDR.zVDRhead : GDR.rVDRhead);
922   for (ix = 0; ix < numVars; ++ix) {
923     status = ValidateVDR (CDF, fp, offset, zVar, debug);
924     if (status != CDF_OK) {
925       cdf_FreeMemory (visit, NULL);
926       return status;
927     }
928     status = ReadVDR (CDF, fp, offset, zVar,
929                       VDR_NUM, &num,
930                       VDR_FLAGS, &flags,
931                       VDR_MAXREC, &lastRec,
932                       VDR_VDRNEXT, &nextVDR,
933                       VDR_CPRorSPR, &cprOffset,
934                       VDR_VXRHEAD, &headVXR,
935                       VDR_VXRTAIL, &tailVXR,
936                       VDR_NULL);
937     if (CDF->singleFile && lastRec > -1) {
938       status = ValidateVariableValueLinks (CDF, fp, lastRec, headVXR, debug);
939       if (status != CDF_OK) {
940         cdf_FreeMemory (visit, NULL);
941         return status;
942       }
943     }
944 /*
945     if (CDF->singleFile && (headVXR != tailVXR) && tailVXR > 0) {
946       status = ValidateVariableValueLinks (CDF, fp, lastRec, tailVXR, debug);
947       if (status != CDF_OK) {
948         cdf_FreeMemory (visit, NULL);
949         return status;
950       }
951     }
952 */
953     if (VARcompressionBITset(flags)) {
954       status = ValidateCPR (fp, cprOffset, debug);
955       if (status != CDF_OK) {
956         cdf_FreeMemory (visit, NULL);
957         return status;
958       }
959     }
960     visit[num] = 1;
961     offset = nextVDR;
962   }
963   for (ix = 0; ix < numVars; ++ix) {
964     if (visit[ix] == 0) {
965       cdf_FreeMemory (visit, NULL);
966       return QuitCDF ("CDF: a variable unreachable in variable link: ",
967                        4, 1, &ix, 0, debug);
968     }
969   }
970   cdf_FreeMemory (visit, NULL);
971   if (offset != 0) {
972     status = ReadVDR (CDF, fp, offset, zVar,
973                       VDR_NUM, &num,
974                       VDR_VDRNEXT, &nextVDR,
975                       VDR_NULL);
976     if (status == CDF_OK) {
977       if (num >= numVars)
978         return QuitCDF ("CDF: a variable unreachable in variable link: ",
979                         4, 2, &num, &numVars, debug);
980       else
981         return QuitCDF ("CDF: a variable is repeated in variable link: ",
982                         4, 2, &num, &numVars, debug);
983     }
984   }
985   return CDF_OK;
986 }
987 
988 /******************************************************************************
989 * ValidateVariableValueLinks.
990 ******************************************************************************/
991 
ValidateVariableValueLinks(struct CDFstruct * CDF,vFILE * fp,Int32 lastRec,Int32 headVXR,Logical debug)992 CDFstatus ValidateVariableValueLinks (struct CDFstruct *CDF, vFILE *fp,
993                                       Int32 lastRec, Int32 headVXR,
994                                       Logical debug)
995 {
996   CDFstatus status;
997 
998   status = ValidateVXR (fp, headVXR, lastRec, debug);
999   if (status != CDF_OK) return status;
1000 
1001   return CDF_OK;
1002 }
1003 
1004 /******************************************************************************
1005 * QuitCDF.
1006 ******************************************************************************/
1007 
QuitCDF(char * why,int size,int num,void * value1,void * value2,Logical debug)1008 CDFstatus QuitCDF (char *why, int size, int num, void *value1, void *value2,
1009                    Logical debug)
1010 {
1011 
1012   if (debug) {
1013     char text[101];
1014     strcpyX (text, why, 100);
1015     if (num == 2) {
1016       if (size == 4)
1017         sprintf (EofS(text), " (%ld vs %ld) ", (long) *(int *)value1,
1018                                                (long) *(int *)value2);
1019       else
1020         sprintf (EofS(text), " (%s vs %s) ", (char *)value1, (char *)value2);
1021     } else {
1022       if (size == 4)
1023         sprintf (EofS(text), " (%ld) ", (long) *(int *)value1);
1024       else
1025         sprintf (EofS(text), " (%s) ", (char *)value1);
1026     }
1027     printf ("ERROR...%s\n", text);
1028   }
1029   return CV2C;
1030 }
1031 
1032