LCOV - code coverage report
Current view: top level - frmts/grib/degrib/g2clib - comunpack.c (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 160 242 66.1 %
Date: 2026-05-29 23:25:07 Functions: 2 2 100.0 %

          Line data    Source code
       1             : #include <float.h>
       2             : #include <limits.h>
       3             : #include <stdio.h>
       4             : #include <stdlib.h>
       5             : #include "grib2.h"
       6             : 
       7             : #ifndef DoubleToFloatClamp_defined
       8             : #define DoubleToFloatClamp_defined
       9          70 : static float DoubleToFloatClamp(double val) {
      10          70 :    if (val >= FLT_MAX) return FLT_MAX;
      11          70 :    if (val <= -FLT_MAX) return -FLT_MAX;
      12          70 :    return (float)val;
      13             : }
      14             : #endif
      15             : 
      16          35 : int comunpack(unsigned char *cpack,g2int cpack_length,g2int lensec,g2int idrsnum,g2int *idrstmpl,g2int ndpts,g2float *fld)
      17             : ////$$$  SUBPROGRAM DOCUMENTATION BLOCK
      18             : //                .      .    .                                       .
      19             : // SUBPROGRAM:    comunpack
      20             : //   PRGMMR: Gilbert          ORG: W/NP11    DATE: 2002-10-29
      21             : //
      22             : // ABSTRACT: This subroutine unpacks a data field that was packed using a
      23             : //   complex packing algorithm as defined in the GRIB2 documentation,
      24             : //   using info from the GRIB2 Data Representation Template 5.2 or 5.3.
      25             : //   Supports GRIB2 complex packing templates with or without
      26             : //   spatial differences (i.e. DRTs 5.2 and 5.3).
      27             : //
      28             : // PROGRAM HISTORY LOG:
      29             : // 2002-10-29  Gilbert
      30             : // 2004-12-16  Gilbert  -  Added test ( provided by Arthur Taylor/MDL )
      31             : //                         to verify that group widths and lengths are
      32             : //                         consistent with section length.
      33             : //
      34             : // USAGE:    int comunpack(unsigned char *cpack,g2int lensec,g2int idrsnum,
      35             : //                         g2int *idrstmpl, g2int ndpts,g2float *fld)
      36             : //   INPUT ARGUMENT LIST:
      37             : //     cpack    - pointer to the packed data field.
      38             : //     lensec   - length of section 7 (used for error checking).
      39             : //     idrsnum  - Data Representation Template number 5.N
      40             : //                Must equal 2 or 3.
      41             : //     idrstmpl - pointer to the array of values for Data Representation
      42             : //                Template 5.2 or 5.3
      43             : //     ndpts    - The number of data values to unpack
      44             : //
      45             : //   OUTPUT ARGUMENT LIST:
      46             : //     fld      - Contains the unpacked data values.  fld must be allocated
      47             : //                with at least ndpts*sizeof(g2float) bytes before
      48             : //                calling this routine.
      49             : //
      50             : // REMARKS: None
      51             : //
      52             : // ATTRIBUTES:
      53             : //   LANGUAGE: C
      54             : //   MACHINE:
      55             : //
      56             : //$$$//
      57             : {
      58             : 
      59          35 :       g2int nbitsd=0,isign;
      60          35 :       g2int j,iofst,ival1,ival2,minsd,itemp,l,k,n,non=0;
      61          35 :       g2int *ifld=NULL,*ifldmiss=NULL;
      62          35 :       g2int *gref=NULL,*gwidth=NULL,*glen=NULL;
      63             :       g2int itype,ngroups,nbitsgref,nbitsgwidth,nbitsglen;
      64             :       g2int msng1,msng2;
      65             :       g2float ref,bscale,dscale,rmiss1,rmiss2;
      66             :       g2int totBit, totLen;
      67          35 :       g2int errorOccurred = 0;
      68             : 
      69             :       //printf('IDRSTMPL: ',(idrstmpl(j),j=1,16)
      70          35 :       rdieee(idrstmpl+0,&ref,1);
      71             : //      printf("SAGTref: %f\n",ref);
      72          35 :       bscale = DoubleToFloatClamp(int_power(2.0,idrstmpl[1]));
      73          35 :       dscale = DoubleToFloatClamp(int_power(10.0,-idrstmpl[2]));
      74          35 :       nbitsgref = idrstmpl[3];
      75          35 :       itype = idrstmpl[4];
      76          35 :       ngroups = idrstmpl[9];
      77          35 :       nbitsgwidth = idrstmpl[11];
      78          35 :       nbitsglen = idrstmpl[15];
      79          35 :       if (idrsnum == 3)
      80          16 :          nbitsd=idrstmpl[17]*8;
      81             : 
      82             :       //   Constant field
      83             : 
      84          35 :       if (ngroups == 0) {
      85          34 :          for (j=0;j<ndpts;j++) fld[j]=ref;
      86           8 :          return(0);
      87             :       }
      88             : 
      89             :       /* To avoid excessive memory allocations. Not completely sure */
      90             :       /* if this test is appropriate (the 10 and 2 are arbitrary), */
      91             :       /* but it doesn't seem to make sense to have ngroups much larger than */
      92             :       /* ndpts */
      93          27 :       if( ngroups < 0 || ngroups - 10 > ndpts / 2 ) {
      94           0 :           return -1;
      95             :       }
      96             : 
      97             :       /* Early test in particular case for more general test below */
      98             :       /* "Test to see if the group widths and lengths are consistent with number of */
      99             :       /*  values, and length of section 7. */
     100          27 :       if( idrstmpl[12] < 0 || idrstmpl[14] < 0 || idrstmpl[14] > ndpts )
     101           0 :           return -1;
     102          27 :       if( nbitsglen == 0 &&
     103           0 :           ((ngroups > 1 && idrstmpl[12] != (ndpts - idrstmpl[14]) / (ngroups - 1)) ||
     104           1 :            idrstmpl[12] * (ngroups-1) + idrstmpl[14] != ndpts) )
     105             :       {
     106           0 :           return -1;
     107             :       }
     108             : 
     109          27 :       iofst=0;
     110          27 :       ifld=(g2int *)calloc(ndpts,sizeof(g2int));
     111             :       //printf("ALLOC ifld: %d %x\n",(int)ndpts,ifld);
     112          27 :       gref=(g2int *)calloc(ngroups,sizeof(g2int));
     113             :       //printf("ALLOC gref: %d %x\n",(int)ngroups,gref);
     114          27 :       gwidth=(g2int *)calloc(ngroups,sizeof(g2int));
     115             :       //printf("ALLOC gwidth: %d %x\n",(int)ngroups,gwidth);
     116          27 :       if( ifld == NULL || gref == NULL || gwidth == NULL )
     117             :       {
     118           0 :           free(ifld);
     119           0 :           free(gref);
     120           0 :           free(gwidth);
     121           0 :           return -1;
     122             :       }
     123             : //
     124             : //  Get missing values, if supplied
     125             : //
     126          27 :       if ( idrstmpl[6] == 1 ) {
     127          17 :          if (itype == 0)
     128          17 :             rdieee(idrstmpl+7,&rmiss1,1);
     129             :          else
     130           0 :             rmiss1=(g2float)idrstmpl[7];
     131             :       }
     132          27 :       if ( idrstmpl[6] == 2 ) {
     133           0 :          if (itype == 0) {
     134           0 :             rdieee(idrstmpl+7,&rmiss1,1);
     135           0 :             rdieee(idrstmpl+8,&rmiss2,1);
     136             :          }
     137             :          else {
     138           0 :             rmiss1=(g2float)idrstmpl[7];
     139           0 :             rmiss2=(g2float)idrstmpl[8];
     140             :          }
     141             :       }
     142             : 
     143             :       //printf("RMISSs: %f %f %f \n",rmiss1,rmiss2,ref);
     144             : //
     145             : //  Extract spatial differencing values, if using DRS Template 5.3
     146             : //
     147          27 :       if (idrsnum == 3) {
     148          16 :          if (nbitsd != 0) {
     149             : // one mistake here should be unsigned int
     150          16 :               int ok = gbit2(cpack, cpack_length, &ival1, iofst,nbitsd) != -1;
     151          16 :               iofst=iofst+nbitsd;
     152             : //              gbit(cpack,&isign,iofst,1);
     153             : //              iofst=iofst+1
     154             : //              gbit(cpack,&ival1,iofst,nbitsd-1);
     155             : //              iofst=iofst+nbitsd-1;
     156             : //              if (isign == 1) ival1=-ival1;
     157          16 :               if (idrstmpl[16] == 2) {
     158             : // one mistake here should be unsigned int
     159          14 :                  ok = ok && gbit2(cpack, cpack_length, &ival2,iofst,nbitsd) != -1;
     160          14 :                  iofst=iofst+nbitsd;
     161             : //                 gbit(cpack,&isign,iofst,1);
     162             : //                 iofst=iofst+1;
     163             : //                 gbit(cpack,&ival2,iofst,nbitsd-1);
     164             : //                 iofst=iofst+nbitsd-1;
     165             : //                 if (isign == 1) ival2=-ival2;
     166             :               }
     167          16 :               ok = ok && gbit2(cpack, cpack_length, &isign,iofst,1) != -1;
     168          16 :               iofst=iofst+1;
     169          16 :               ok = ok && gbit2(cpack, cpack_length, &minsd,iofst,nbitsd-1) != - 1;
     170          16 :               iofst=iofst+nbitsd-1;
     171             : 
     172          16 :               if (!ok)
     173             :               {
     174           1 :                   free(ifld);
     175           1 :                   free(gref);
     176           1 :                   free(gwidth);
     177           1 :                   return -1;
     178             :               }
     179             : 
     180          15 :               if (isign == 1 && minsd != INT_MIN) minsd=-minsd;
     181             :          }
     182             :          else {
     183           0 :               ival1=0;
     184           0 :               ival2=0;
     185           0 :               minsd=0;
     186             :          }
     187             :        //printf("SDu %ld %ld %ld %ld \n",ival1,ival2,minsd,nbitsd);
     188             :       }
     189             : //
     190             : //  Extract Each Group's reference value
     191             : //
     192             :       //printf("SAG1: %ld %ld %ld \n",nbitsgref,ngroups,iofst);
     193          26 :       if (nbitsgref != 0) {
     194          26 :          if( gbits(cpack,cpack_length,gref+0,iofst,nbitsgref,0,ngroups) != 0 )
     195             :          {
     196           0 :              free(ifld);
     197           0 :              free(gwidth);
     198           0 :              free(gref);
     199           0 :              return -1;
     200             :          }
     201          26 :          itemp=nbitsgref*ngroups;
     202          26 :          iofst=iofst+itemp;
     203          26 :          if (itemp%8 != 0) iofst=iofst+(8-(itemp%8));
     204             :       }
     205             : #if 0
     206             :       else {
     207             :          for (j=0;j<ngroups;j++)
     208             :               gref[j]=0;
     209             :       }
     210             : #endif
     211             : 
     212             : //
     213             : //  Extract Each Group's bit width
     214             : //
     215             :       //printf("SAG2: %ld %ld %ld %ld \n",nbitsgwidth,ngroups,iofst,idrstmpl[10]);
     216          26 :       if (nbitsgwidth != 0) {
     217          26 :          if( gbits(cpack,cpack_length,gwidth+0,iofst,nbitsgwidth,0,ngroups) != 0 )
     218             :          {
     219           0 :              free(ifld);
     220           0 :              free(gwidth);
     221           0 :              free(gref);
     222           0 :              return -1;
     223             :          }
     224          26 :          itemp=nbitsgwidth*ngroups;
     225          26 :          iofst=iofst+itemp;
     226          26 :          if (itemp%8 != 0) iofst=iofst+(8-(itemp%8));
     227             :       }
     228             : #if 0
     229             :       else {
     230             :          for (j=0;j<ngroups;j++)
     231             :                 gwidth[j]=0;
     232             :       }
     233             : #endif
     234             : 
     235      105696 :       for (j=0;j<ngroups;j++)
     236             :       {
     237      105670 :           if( gwidth[j] > INT_MAX - idrstmpl[10] )
     238             :           {
     239           0 :              free(ifld);
     240           0 :              free(gwidth);
     241           0 :              free(gref);
     242           0 :              return -1;
     243             :           }
     244      105670 :           gwidth[j]=gwidth[j]+idrstmpl[10];
     245             :       }
     246             : 
     247             : //
     248             : //  Extract Each Group's length (number of values in each group)
     249             : //
     250          26 :       glen=(g2int *)calloc(ngroups,sizeof(g2int));
     251          26 :       if( glen == NULL )
     252             :       {
     253           0 :         free(ifld);
     254           0 :         free(gwidth);
     255           0 :         free(gref);
     256           0 :         return -1;
     257             :       }
     258             :       //printf("ALLOC glen: %d %x\n",(int)ngroups,glen);
     259             :       //printf("SAG3: %ld %ld %ld %ld %ld \n",nbitsglen,ngroups,iofst,idrstmpl[13],idrstmpl[12]);
     260          26 :       if (nbitsglen != 0) {
     261          26 :          if( gbits(cpack,cpack_length,glen,iofst,nbitsglen,0,ngroups) != 0 )
     262             :          {
     263           0 :             free(ifld);
     264           0 :             free(gwidth);
     265           0 :             free(glen);
     266           0 :             free(gref);
     267           0 :              return -1;
     268             :          }
     269          26 :          itemp=nbitsglen*ngroups;
     270          26 :          iofst=iofst+itemp;
     271          26 :          if (itemp%8 != 0) iofst=iofst+(8-(itemp%8));
     272             :       }
     273             : #if 0
     274             :       else {
     275             :          for (j=0;j<ngroups;j++)
     276             :               glen[j]=0;
     277             :       }
     278             : #endif
     279             : 
     280             :       // Note: iterate only to ngroups - 1 since we override just after the
     281             :       // loop. Otherwise the security checks in the loop might trigger, like
     282             :       // on band 23 of
     283             :       // https://nomads.ncep.noaa.gov/pub/data/nccf/com/blend/prod/blend.20200605/16/grib2/blend.t16z.master.f001.co.grib2
     284      105670 :       for (j=0;j<ngroups - 1;j++)
     285             :       {
     286      105644 :            if( glen[j] < 0 ||
     287      105644 :                (idrstmpl[13] != 0 && glen[j] > INT_MAX / idrstmpl[13]) ||
     288      105644 :                glen[j] *  idrstmpl[13] > INT_MAX - idrstmpl[12] )
     289             :            {
     290           0 :                 free(ifld);
     291           0 :                 free(gwidth);
     292           0 :                 free(glen);
     293           0 :                 free(gref);
     294           0 :                 return -1;
     295             :            }
     296      105644 :            glen[j]=(glen[j]*idrstmpl[13])+idrstmpl[12];
     297             :       }
     298          26 :       glen[ngroups-1]=idrstmpl[14];
     299             : //
     300             : //  Test to see if the group widths and lengths are consistent with number of
     301             : //  values, and length of section 7.
     302             : //
     303          26 :       totBit = 0;
     304          26 :       totLen = 0;
     305      105696 :       for (j=0;j<ngroups;j++) {
     306             :         g2int width_mult_len;
     307      105670 :         if( gwidth[j] < 0 || glen[j] < 0 ||
     308      105670 :             (gwidth[j] > 0 && glen[j] > INT_MAX / gwidth[j]) )
     309             :         {
     310           0 :             errorOccurred = 1;
     311           0 :             break;
     312             :         }
     313      105670 :         width_mult_len = gwidth[j]*glen[j];
     314      105670 :         if( totBit > INT_MAX - width_mult_len )
     315             :         {
     316           0 :             errorOccurred = 1;
     317           0 :             break;
     318             :         }
     319      105670 :         totBit += width_mult_len;
     320      105670 :         if( totLen > INT_MAX - glen[j] )
     321             :         {
     322           0 :             errorOccurred = 1;
     323           0 :             break;
     324             :         }
     325      105670 :         totLen += glen[j];
     326             :       }
     327          26 :       if (errorOccurred || totLen != ndpts || totBit / 8. > lensec) {
     328           0 :         free(ifld);
     329           0 :         free(gwidth);
     330           0 :         free(glen);
     331           0 :         free(gref);
     332           0 :         return 1;
     333             :       }
     334             : //
     335             : //  For each group, unpack data values
     336             : //
     337          26 :       if ( idrstmpl[6] == 0 ) {        // no missing values
     338           9 :          n=0;
     339       18401 :          for (j=0;j<ngroups;j++) {
     340       18392 :            if (gwidth[j] != 0) {
     341       17274 :              if( gbits(cpack,cpack_length,ifld+n,iofst,gwidth[j],0,glen[j]) != 0 )
     342             :              {
     343           0 :                  free(ifld);
     344           0 :                  free(gwidth);
     345           0 :                  free(glen);
     346           0 :                  free(gref);
     347           0 :                  return -1;
     348             :              }
     349      270270 :              for (k=0;k<glen[j];k++) {
     350      252996 :                ifld[n]=ifld[n]+gref[j];
     351      252996 :                n=n+1;
     352             :              }
     353             :            }
     354             :            else {
     355        2323 :              for (l=n;l<n+glen[j];l++) ifld[l]=gref[j];
     356        1118 :              n=n+glen[j];
     357             :            }
     358       18392 :            iofst=iofst+(gwidth[j]*glen[j]);
     359             :          }
     360             :       }
     361          17 :       else if ( idrstmpl[6]==1 || idrstmpl[6]==2 ) {
     362             :          // missing values included
     363          17 :          ifldmiss=(g2int *)malloc(ndpts*sizeof(g2int));
     364             :          //printf("ALLOC ifldmiss: %d %x\n",(int)ndpts,ifldmiss);
     365             :          //for (j=0;j<ndpts;j++) ifldmiss[j]=0;
     366          17 :          n=0;
     367          17 :          non=0;
     368       87295 :          for (j=0;j<ngroups;j++) {
     369             :            //printf(" SAGNGP %d %d %d %d\n",j,gwidth[j],glen[j],gref[j]);
     370       87278 :            if (gwidth[j] != 0) {
     371       75982 :              msng1=(g2int)int_power(2.0,gwidth[j])-1;
     372       75982 :              msng2=msng1-1;
     373       75982 :              if( gbits(cpack,cpack_length,ifld+n,iofst,gwidth[j],0,glen[j]) != 0 )
     374             :              {
     375           0 :                  free(ifld);
     376           0 :                  free(gwidth);
     377           0 :                  free(glen);
     378           0 :                  free(gref);
     379           0 :                  free(ifldmiss);
     380           0 :                  return -1;
     381             :              }
     382       75982 :              iofst=iofst+(gwidth[j]*glen[j]);
     383     1157860 :              for (k=0;k<glen[j];k++) {
     384     1081880 :                if (ifld[n] == msng1) {
     385       86597 :                   ifldmiss[n]=1;
     386             :                   //ifld[n]=0;
     387             :                }
     388      995279 :                else if (idrstmpl[6]==2 && ifld[n]==msng2) {
     389           0 :                   ifldmiss[n]=2;
     390             :                   //ifld[n]=0;
     391             :                }
     392             :                else {
     393      995279 :                   ifldmiss[n]=0;
     394      995279 :                   ifld[non++]=ifld[n]+gref[j];
     395             :                }
     396     1081880 :                n++;
     397             :              }
     398             :            }
     399             :            else {
     400       11296 :              msng1=(g2int)int_power(2.0,nbitsgref)-1;
     401       11296 :              msng2=msng1-1;
     402       11296 :              if (gref[j] == msng1) {
     403     1303530 :                 for (l=n;l<n+glen[j];l++) ifldmiss[l]=1;
     404             :              }
     405           0 :              else if (idrstmpl[6]==2 && gref[j]==msng2) {
     406           0 :                 for (l=n;l<n+glen[j];l++) ifldmiss[l]=2;
     407             :              }
     408             :              else {
     409           0 :                 for (l=n;l<n+glen[j];l++) ifldmiss[l]=0;
     410           0 :                 for (l=non;l<non+glen[j];l++) ifld[l]=gref[j];
     411           0 :                 non += glen[j];
     412             :              }
     413       11296 :              n=n+glen[j];
     414             :            }
     415             :          }
     416             :       }
     417             : 
     418          26 :       if ( gref != 0 ) free(gref);
     419          26 :       if ( gwidth != 0 ) free(gwidth);
     420          26 :       if ( glen != 0 ) free(glen);
     421             : //
     422             : //  If using spatial differences, add overall min value, and
     423             : //  sum up recursively
     424             : //
     425             :       //printf("SAGod: %ld %ld\n",idrsnum,idrstmpl[16]);
     426          26 :       if (idrsnum == 3) {         // spatial differencing
     427          15 :          if (idrstmpl[16] == 1) {      // first order
     428           2 :             ifld[0]=ival1;
     429           2 :             if ( idrstmpl[6] == 0 ) itemp=ndpts;        // no missing values
     430           1 :             else  itemp=non;
     431       19477 :             for (n=1;n<itemp;n++) {
     432       19475 :                if( (minsd > 0 && ifld[n] > INT_MAX - minsd) ||
     433       19475 :                    (minsd < 0 && ifld[n] < INT_MIN - minsd) )
     434             :                {
     435           0 :                    free(ifldmiss);
     436           0 :                    free(ifld);
     437           0 :                    return -1;
     438             :                }
     439       19475 :                ifld[n]=ifld[n]+minsd;
     440       19475 :                if( (ifld[n-1] > 0 && ifld[n] > INT_MAX - ifld[n-1]) ||
     441       19475 :                    (ifld[n-1] < 0 && ifld[n] < INT_MIN - ifld[n-1]) )
     442             :                {
     443           0 :                    free(ifldmiss);
     444           0 :                    free(ifld);
     445           0 :                    return -1;
     446             :                }
     447       19475 :                ifld[n]=ifld[n]+ifld[n-1];
     448             :             }
     449             :          }
     450          13 :          else if (idrstmpl[16] == 2) {    // second order
     451          13 :             ifld[0]=ival1;
     452          13 :             ifld[1]=ival2;
     453          13 :             if ( idrstmpl[6] == 0 ) itemp=ndpts;        // no missing values
     454          11 :             else  itemp=non;
     455      461235 :             for (n=2;n<itemp;n++) {
     456             :                /* Lazy way of detecting int overflows: operate on double */
     457      461222 :                double tmp = (double)ifld[n]+(double)minsd+(2.0 * ifld[n-1])-ifld[n-2];
     458      461222 :                if( tmp > INT_MAX || tmp < INT_MIN )
     459             :                {
     460           0 :                    free(ifldmiss);
     461           0 :                    free(ifld);
     462           0 :                    return -1;
     463             :                }
     464      461222 :                ifld[n]=(int)tmp;
     465             :             }
     466             :          }
     467             :       }
     468             : //
     469             : //  Scale data back to original form
     470             : //
     471             :       //printf("SAGT: %f %f %f\n",ref,bscale,dscale);
     472          26 :       if ( idrstmpl[6] == 0 ) {        // no missing values
     473      254210 :          for (n=0;n<ndpts;n++) {
     474      254201 :             fld[n]=(((g2float)ifld[n]*bscale)+ref)*dscale;
     475             :          }
     476             :       }
     477          17 :       else if ( idrstmpl[6]==1 || idrstmpl[6]==2 ) {
     478             :          // missing values included
     479          17 :          non=0;
     480     2374130 :          for (n=0;n<ndpts;n++) {
     481     2374110 :             if ( ifldmiss[n] == 0 ) {
     482      995279 :                fld[n]=(((g2float)ifld[non++]*bscale)+ref)*dscale;
     483             :                //printf(" SAG %d %f %d %f %f %f\n",n,fld[n],ifld[non-1],bscale,ref,dscale);
     484             :             }
     485     1378830 :             else if ( ifldmiss[n] == 1 )
     486     1378830 :                fld[n]=rmiss1;
     487           0 :             else if ( ifldmiss[n] == 2 )
     488           0 :                fld[n]=rmiss2;
     489             :          }
     490          17 :          if ( ifldmiss != 0 ) free(ifldmiss);
     491             :       }
     492             : 
     493          26 :       if ( ifld != 0 ) free(ifld);
     494             : 
     495          26 :       return(0);
     496             : 
     497             : }

Generated by: LCOV version 1.14