Skip to content
This repository was archived by the owner on Sep 1, 2022. It is now read-only.

Commit 028a22a

Browse files
committed
Fixes #445: GRIB1 data length overflow
1 parent 23eb4e3 commit 028a22a

File tree

2 files changed

+53
-5
lines changed

2 files changed

+53
-5
lines changed

grib/src/main/java/ucar/nc2/grib/grib1/Grib1RecordScanner.java

+44-4
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,14 @@ static public boolean isValidFile(RandomAccessFile raf) {
8484
int len = GribNumbers.uint3(raf);
8585
int edition = raf.read(); // read at byte 8
8686
if (edition != 1) return false;
87-
87+
88+
/* Due to a trick done by ECMWF's GRIBEX to support large GRIBs, we need a special treatment
89+
* to fix the length of the GRIB message. See:
90+
* https://software.ecmwf.int/wiki/display/EMOS/Changes+in+cycle+000281
91+
* https://github.com/Unidata/thredds/issues/445
92+
*/
93+
len = getFixedTotalLengthEcmwfLargeGrib(raf,len);
94+
8895
// check ending = 7777
8996
if (len > raf.length()) return false;
9097
if (allowBadIsLength) return true;
@@ -100,7 +107,40 @@ static public boolean isValidFile(RandomAccessFile raf) {
100107
}
101108
}
102109

103-
////////////////////////////////////////////////////////////
110+
static int getFixedTotalLengthEcmwfLargeGrib(RandomAccessFile raf, int len) throws IOException{
111+
int lenActual=len;
112+
//int lenS4Actual=0;
113+
//int sizeSection4=0;
114+
if ((len & 0x800000) == 0x800000) {
115+
long pos0 = raf.getFilePointer(); // remember the actual pos
116+
int lenS1 = GribNumbers.uint3(raf); // section1Length
117+
raf.skipBytes(1); // table2Version
118+
if (GribNumbers.uint(raf) == 98) { // center (if ECMWF make the black magic)
119+
raf.skipBytes(2); // generatingProcessIdentifier, gridDefinition
120+
int s1f = GribNumbers.uint(raf); // section1Flags
121+
raf.skipBytes(lenS1 - (3 + 5)); // skips to next section
122+
int lenS2 = 0;
123+
int lenS3 = 0;
124+
if ((s1f & 128) == 128) { // section2 GDS exists
125+
lenS2 = GribNumbers.uint3(raf); // section2Length
126+
raf.skipBytes(lenS2 - 3); // skips to next section
127+
}
128+
if ((s1f & 64) == 64) { // section3 BMS exists
129+
lenS3 = GribNumbers.uint3(raf); // section3Length
130+
raf.skipBytes(lenS3 - 3); // skips to next section
131+
}
132+
int lenS4 = GribNumbers.uint3(raf); // section4Length
133+
if (lenS4 < 120) { // here we are!!!!
134+
lenActual = (len & 0x7FFFFF) * 120 - lenS4 + 4; // the actual totalLength
135+
//lenS4Actual = lenActual - 8 - lenS1 - lenS2 - lenS3 - 4; // the actual length for section4
136+
}
137+
}
138+
raf.seek(pos0); // recall the pos
139+
}
140+
return lenActual;
141+
}
142+
143+
////////////////////////////////////////////////////////////
104144

105145
private Map<Long, Grib1SectionGridDefinition> gdsMap = new HashMap<>();
106146
private ucar.unidata.io.RandomAccessFile raf = null;
@@ -199,10 +239,10 @@ public Grib1Record next() throws IOException {
199239
if (debug) System.out.printf(" read until %d grib ending at %d header ='%s' foundEnding=%s%n",
200240
raf.getFilePointer(), ending, StringUtil2.cleanup(header), foundEnding);
201241

202-
if (!foundEnding && allowBadIsLength)
242+
if (!foundEnding && (allowBadIsLength || is.isMessageLengthFixed))
203243
foundEnding = checkEnding(dataSection.getStartingPosition() + dataSection.getLength());
204244

205-
if (!foundEnding && allowBadDsLength) {
245+
if (!foundEnding && (allowBadDsLength || is.isMessageLengthFixed)) {
206246
foundEnding = true;
207247
}
208248

grib/src/main/java/ucar/nc2/grib/grib1/Grib1SectionIndicator.java

+9-1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ public class Grib1SectionIndicator {
4949

5050
private final long messageLength;
5151
private final long startPos;
52+
private final int messageLengthNotFixed;
53+
boolean isMessageLengthFixed=false;
5254

5355
/**
5456
* Read Grib2SectionIndicator from raf.
@@ -65,15 +67,21 @@ public Grib1SectionIndicator(RandomAccessFile raf) throws IOException {
6567
if (b[i] != MAGIC[i])
6668
throw new IllegalArgumentException("Not a GRIB record");
6769

68-
messageLength = GribNumbers.uint3(raf);
70+
messageLengthNotFixed = GribNumbers.uint3(raf);
6971
int edition = raf.read();
7072
if (edition != 1)
7173
throw new IllegalArgumentException("Not a GRIB-1 record");
74+
messageLength = Grib1RecordScanner.getFixedTotalLengthEcmwfLargeGrib(raf, messageLengthNotFixed);
75+
if(messageLength!=messageLengthNotFixed) {
76+
isMessageLengthFixed = true;
77+
}
7278
}
7379

7480
public Grib1SectionIndicator(long startPos, long messageLength) {
7581
this.startPos = startPos;
7682
this.messageLength = messageLength;
83+
this.messageLengthNotFixed = (int)messageLength;
84+
this.isMessageLengthFixed = false;
7785
}
7886

7987
/**

0 commit comments

Comments
 (0)