Skip to content

Commit 68cc9fe

Browse files
Merge pull request #595 from EricEngle-NOAA/develop
Potential fix for #438.
2 parents 98aec44 + 098b2be commit 68cc9fe

File tree

9 files changed

+134
-14
lines changed

9 files changed

+134
-14
lines changed

.github/workflows/MacOS.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,14 @@ jobs:
6666
uses: actions/cache@v4
6767
with:
6868
path: ~/png
69-
key: png-${{ runner.os }}-1.6.37-macOS
69+
key: png-${{ runner.os }}-1.6.45-macOS
7070

7171
- name: build-png
7272
if: steps.cache-png.outputs.cache-hit != 'true'
7373
run: |
74-
wget https://github.com/glennrp/libpng/archive/refs/tags/v1.6.37.tar.gz &> /dev/null
75-
tar zxf v1.6.37.tar.gz
76-
cd libpng-1.6.37
74+
wget https://github.com/glennrp/libpng/archive/refs/tags/v1.6.45.tar.gz &> /dev/null
75+
tar zxf v1.6.45.tar.gz
76+
cd libpng-1.6.45
7777
mkdir build
7878
cd build
7979
cmake .. -DCMAKE_INSTALL_PREFIX=~/png -DCMAKE_C_FLAGS="-Wno-implicit-function-declaration" -DPNG_ARM_NEON=off

src/g2_addfield.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ g2_addfield(unsigned char *cgrib, g2int ipdsnum, g2int *ipdstmpl,
120120

121121
/* Check for GRIB header and terminator. Translate the error codes
122122
* to the legacy G2 error codes. */
123-
if ((ret = g2c_check_msg(cgrib, &lencurr, 1)))
123+
if ((ret = g2c_check_msg(cgrib, &lencurr, 1, 3)))
124124
{
125125
if (ret == G2C_ENOTGRIB)
126126
return G2_ADD_MSG_INIT;

src/g2_addgrid.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ g2_addgrid(unsigned char *cgrib, g2int *igds, g2int *igdstmpl, g2int *ideflist,
7474

7575
/* Check for GRIB header and terminator. Translate the error codes
7676
* to the legacy G2 error codes. */
77-
if ((ret = g2c_check_msg(cgrib, &lencurr, 1)))
77+
if ((ret = g2c_check_msg(cgrib, &lencurr, 1, 2)))
7878
{
7979
if (ret == G2C_ENOTGRIB)
8080
return G2_ADD_MSG_INIT;

src/g2_addlocal.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ g2_addlocal(unsigned char *cgrib, unsigned char *csec2, g2int lcsec2)
4747

4848
/* Check for GRIB header and terminator. Translate the error codes
4949
* to the legacy G2 error codes. */
50-
if ((ret = g2c_check_msg(cgrib, &lencurr, 1)))
50+
if ((ret = g2c_check_msg(cgrib, &lencurr, 1, 1)))
5151
{
5252
if (ret == G2C_ENOTGRIB)
5353
return G2_ADD_MSG_INIT;

src/g2_gribend.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ g2_gribend(unsigned char *cgrib)
4646

4747
/* Check for GRIB header and terminator. Translate the error codes
4848
* to the legacy G2 error codes. */
49-
if ((ret = g2c_check_msg(cgrib, &lencurr, 1)))
49+
if ((ret = g2c_check_msg(cgrib, &lencurr, 1, 4)))
5050
{
5151
if (ret == G2C_ENOTGRIB)
5252
return G2_ADD_MSG_INIT;

src/grib2_int.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ int pack_gp(g2int *kfildo, g2int *ic, g2int *nxy,
384384
g2int *novref, g2int *lbitref, g2int *ier);
385385

386386
/* Check the message header and check for message termination. */
387-
int g2c_check_msg(unsigned char *cgrib, g2int *lencurr, int verbose);
387+
int g2c_check_msg(unsigned char *cgrib, g2int *lencurr, int verbose, int from);
388388

389389
/* Basic file I/O. */
390390
int g2c_file_io(FILE *f, int write, int g2ctype, void *var);

src/util.c

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,30 +7,48 @@
77
#include "grib2_int.h"
88
#include <stdarg.h>
99

10+
/** If pthreads are enabled, use externally-defined mutex for
11+
* thread-safety. */
12+
EXTERN_MUTEX(m);
13+
1014
/**
1115
* Check for 'GRIB' at the beginning of a GRIB message, and check to
1216
* see if the message is already terminated with '7777'.
1317
*
18+
* On rare occasions, the last 4 bytes of section 7 (data section)
19+
* can be the GRIB terminating string of '7777'. This function
20+
* accommodates for this by tracking which function called g2c_check_msg()
21+
* via the from argument (see below).
22+
*
1423
* @param cgrib Buffer that contains the GRIB message.
1524
* @param lencurr Pointer that gets the length of the GRIB message.
1625
* @param verbose If non-zero, print any error messages to stdout.
26+
* @param from Mapping of where this function was called from.
27+
* - 1 = From g2_addlocal()
28+
* - 2 = From g2_addgrid()
29+
* - 3 = From g2_addfield()
30+
* - 4 = From g2_gribend()
1731
*
1832
* @return
1933
* - ::G2C_NOERROR No error.
2034
* - ::G2C_ENOTGRIB GRIB header not found.
2135
* - ::G2C_EMSGCOMPLETE GRIB message already complete.
2236
*
2337
* @author Ed Hartnett @date Nov 11, 2021
38+
* @author Eric Engle
2439
*/
2540
int
26-
g2c_check_msg(unsigned char *cgrib, g2int *lencurr, int verbose)
41+
g2c_check_msg(unsigned char *cgrib, g2int *lencurr, int verbose, int from)
2742
{
2843
unsigned char G = 0x47; /* 'G' */
2944
unsigned char R = 0x52; /* 'R' */
3045
unsigned char I = 0x49; /* 'I' */
3146
unsigned char B = 0x42; /* 'B' */
3247
unsigned char seven = 0x37; /* '7' */
3348

49+
int iret = 0;
50+
static int last_from = 0; /* Keep last value of from arg */
51+
3452
assert(cgrib && lencurr);
3553

3654
/* Check to see if beginning of GRIB message exists. */
@@ -39,6 +57,10 @@ g2c_check_msg(unsigned char *cgrib, g2int *lencurr, int verbose)
3957
if (verbose)
4058
printf("GRIB not found in given message. A call to routine g2_create() "
4159
"is required to to initialize GRIB messge.\n");
60+
/* Update last_from. */
61+
MUTEX_LOCK(m);
62+
last_from = from;
63+
MUTEX_UNLOCK(m);
4264
return G2C_ENOTGRIB;
4365
}
4466

@@ -49,12 +71,26 @@ g2c_check_msg(unsigned char *cgrib, g2int *lencurr, int verbose)
4971
if (cgrib[*lencurr - 4] == seven && cgrib[*lencurr - 3] == seven &&
5072
cgrib[*lencurr - 2] == seven && cgrib[*lencurr - 1] == seven)
5173
{
52-
if (verbose)
53-
printf("GRIB message already complete. Cannot add new section.\n");
54-
return G2C_EMSGCOMPLETE;
74+
/* Allow this to occur if this is called from g2_gribend (from = 4)
75+
* and previous call was from g2_addfield where last_from = 3. */
76+
if (from == 4 && last_from == 3)
77+
{
78+
iret = G2C_NOERROR;
79+
}
80+
else
81+
{
82+
if (verbose)
83+
printf("GRIB message already complete. Cannot add new section.\n");
84+
iret = G2C_EMSGCOMPLETE;
85+
}
5586
}
5687

57-
return G2C_NOERROR;
88+
/* Update last_from. */
89+
MUTEX_LOCK(m);
90+
last_from = from;
91+
MUTEX_UNLOCK(m);
92+
93+
return iret;
5894
}
5995

6096
#ifdef LOGGING

tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ endif()
179179
g2c_test(tst_g2_create)
180180
g2c_test(tst_g2_addgrid)
181181
g2c_test(tst_g2_addfield)
182+
g2c_test(tst_rare_packing_gribend)
182183
g2c_test(tst_decode)
183184
g2c_test(tst_gbits)
184185
g2c_test(tst_gridtemplates)

tests/tst_rare_packing_gribend.c

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/* This is a test for the NCEPLIBS-g2c project. This test is for a rare scenario where
2+
* the last 4 bytes of the packed data section could be all 55 or hex 0x37, which when
3+
* converted to ASCII, will resemble the GRIB end message terminator of "7777".
4+
*
5+
* This test purposely builds a very small GRIB2 message, with data values purposely
6+
* set so that when using simple packing with no scaling and nbits = 0, will make
7+
* the last 4 bytes of the packed data mimic the GRIB terminator.
8+
*
9+
* Eric Engle 3/17/25
10+
*/
11+
12+
#include "grib2_int.h"
13+
#include <stdio.h>
14+
#include <stdlib.h>
15+
16+
#define SEC0_LEN 16
17+
#define SEC1_LEN 21
18+
#define SEC3_LEN 72
19+
#define SEC4_LEN 58
20+
#define SEC5_LEN 21
21+
#define SEC6_LEN 6
22+
#define SEC7_LEN 11
23+
#define FULL_MSG_LEN 209
24+
25+
int
26+
main()
27+
{
28+
printf("Testing rare packing condition and grid end.\n");
29+
printf("Testing full message creation (expect and ignore error messages)...\n");
30+
{
31+
unsigned char cgrib[FULL_MSG_LEN];
32+
g2int listsec0[2] = {0, 2};
33+
g2int listsec1[13] = {7, 0, 2, 1, 1, 2023, 9, 29, 0, 0, 0, 0, 1};
34+
g2int igds[5] = {0, 6, 0, 0, 0};
35+
g2int igdstmpl[19] = {6, 0, 0, 0, 0, 0, 0, 3, 2, 0, 0, 0, 0, 0, 0, 0, 50000, 50000, 64};
36+
g2int ipdsnum = 8;
37+
g2int ipdstmpl[29] = {1, 8, 2, 0, 250, 0, 0, 1, 0, 1, 0, 0, 255, 0, 0, 2023, 9, 30, 0, 0, 0, 1, 0, 1, 2, 1, 24, 255, 0};
38+
float coordlist[1] = {1};
39+
g2int numcoord = 0;
40+
g2int idrsnum = 0; /* Grid Point Data - Simple Packing (see Template 5.0) */
41+
g2int idrstmpl[5] = {0, 0, 0, 0, 0};
42+
float fld[6] = {0.0, 176.9375, 54.9, 55.1, 54.7, 55.3};
43+
g2int ngrdpts = 6;
44+
g2int ibmap = 255; // No bit map
45+
g2int bmap[6] = {1, 1, 1, 1, 1, 1};
46+
int ret;
47+
48+
/* Initialize empty message to quiet valgrind errors. */
49+
for (int i = 0; i < FULL_MSG_LEN; i++)
50+
cgrib[i] = 0;
51+
52+
/* Create the message, filling in sections 0 and 1. */
53+
printf("Calling g2_create()... ");
54+
ret = g2_create(cgrib, listsec0, listsec1);
55+
printf("ret = %d\n", ret);
56+
if (ret != SEC0_LEN + SEC1_LEN)
57+
return 1;
58+
59+
/* Add section 3. */
60+
printf("Calling g2_addgrid()... ");
61+
ret = g2_addgrid(cgrib, igds, igdstmpl, NULL, 0);
62+
printf("ret = %d\n", ret);
63+
if (ret != SEC0_LEN + SEC1_LEN + SEC3_LEN)
64+
return 1;
65+
66+
/* Add sections 4, 5, 6, and 7. */
67+
printf("Calling g2_addfield()... ");
68+
ret = g2_addfield(cgrib, ipdsnum, ipdstmpl, coordlist, numcoord,
69+
idrsnum, idrstmpl, fld, ngrdpts, ibmap, bmap);
70+
printf("ret = %d\n", ret);
71+
if (ret != SEC0_LEN + SEC1_LEN + SEC3_LEN + SEC4_LEN + SEC5_LEN + SEC6_LEN + SEC7_LEN)
72+
return 1;
73+
74+
/* Add section 8. */
75+
printf("Calling g2_gribend()... ");
76+
ret = g2_gribend(cgrib);
77+
if (ret != FULL_MSG_LEN)
78+
return 1;
79+
}
80+
printf("ok!\n");
81+
printf("SUCCESS!\n");
82+
return 0;
83+
}

0 commit comments

Comments
 (0)