LCOV - code coverage report
Current view: top level - frmts/grib/degrib/g2clib - aecunpack.c (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 31 39 79.5 %
Date: 2024-05-06 11:10:03 Functions: 1 1 100.0 %

          Line data    Source code
       1             : #include <stdio.h>
       2             : #include <stdlib.h>
       3             : #include <limits.h>
       4             : #include "grib2.h"
       5             : 
       6             : #include "libaec.h"
       7             : 
       8             : // Cf https://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_doc/grib2_temp5-42.shtml
       9             : // and https://github.com/erget/wgrib2/commit/07b0f6fcb9669e0e3285318f50d516731b6956b2
      10             : 
      11           1 : g2int aecunpack(unsigned char *cpack,g2int len,g2int *idrstmpl,g2int ndpts,
      12             :                 g2float *fld)
      13             : {
      14             : 
      15           1 :       g2int  iret = 0;
      16             :       g2float  refV;
      17             : 
      18           1 :       rdieee(idrstmpl+0,&refV,1);
      19           1 :       g2float bscale = (g2float)int_power(2.0,idrstmpl[1]);
      20           1 :       g2float dscale = (g2float)int_power(10.0,-idrstmpl[2]);
      21           1 :       g2float bdscale = bscale * dscale;
      22           1 :       g2float refD = refV * dscale;
      23             : 
      24           1 :       g2int nbits = idrstmpl[3];
      25             : //
      26             : //  if nbits equals 0, we have a constant field where the reference value
      27             : //  is the data value at each gridpoint
      28             : //
      29           1 :       if (nbits != 0) {
      30           1 :          int nbytes_per_sample = (nbits + 7) / 8;
      31           1 :          if( ndpts != 0 && nbytes_per_sample > INT_MAX / ndpts )
      32             :          {
      33           0 :              return 1;
      34             :          }
      35           1 :          g2int* ifld=(g2int *)calloc(ndpts,sizeof(g2int));
      36             :          // Was checked just before
      37             :          // coverity[integer_overflow,overflow_sink]
      38           1 :          unsigned char* ctemp=(unsigned char *)calloc((size_t)(ndpts) * nbytes_per_sample,1);
      39           1 :          if ( ifld == NULL || ctemp == NULL) {
      40           0 :             fprintf(stderr, "Could not allocate space in aecunpack.\n"
      41             :                     "Data field NOT unpacked.\n");
      42           0 :             free(ifld);
      43           0 :             free(ctemp);
      44           0 :             return(1);
      45             :          }
      46             : 
      47           1 :          struct aec_stream strm = {0};
      48           1 :          strm.flags = idrstmpl[5]; // CCSDS compression options mask
      49           1 :          strm.bits_per_sample = nbits;
      50           1 :          strm.block_size = idrstmpl[6];
      51           1 :          strm.rsi = idrstmpl[7]; // Restart interval
      52             : 
      53           1 :          strm.next_in = cpack;
      54           1 :          strm.avail_in = len;
      55           1 :          strm.next_out = ctemp;
      56           1 :          strm.avail_out = (size_t)(ndpts) * nbytes_per_sample;
      57             : 
      58             :          // Note: libaec doesn't seem to be very robust to invalid inputs...
      59           1 :          int status = aec_buffer_decode(&strm);
      60           1 :          if (status != AEC_OK)
      61             :          {
      62           0 :              fprintf(stderr, "aec_buffer_decode() failed with return code %d", status);
      63           0 :              iret = 1;
      64             :          }
      65             :          else
      66             :          {
      67           1 :              gbits(ctemp,ndpts * nbytes_per_sample,ifld,0,nbytes_per_sample*8,0,ndpts);
      68             :              g2int j;
      69      405901 :              for (j=0;j<ndpts;j++) {
      70      405900 :                 fld[j] = refD + bdscale*(g2float)(ifld[j]);
      71             :              }
      72             :          }
      73           1 :          free(ctemp);
      74           1 :          free(ifld);
      75             :       }
      76             :       else {
      77             :          g2int j;
      78           0 :          for (j=0;j<ndpts;j++) fld[j]=refD;
      79             :       }
      80             : 
      81           1 :       return(iret);
      82             : }

Generated by: LCOV version 1.14