3232import org .apache .tsfile .enums .TSDataType ;
3333import org .apache .tsfile .utils .Binary ;
3434import org .apache .tsfile .utils .BitMap ;
35- import org .apache .tsfile .utils .BytesUtils ;
3635import org .apache .tsfile .utils .Pair ;
3736import org .apache .tsfile .utils .ReadWriteIOUtils ;
3837import org .apache .tsfile .write .UnSupportedDataTypeException ;
@@ -116,12 +115,19 @@ private static InsertTabletStatement deserializeStatementFromTabletFormat(
116115 intern (ReadWriteIOUtils .readString (byteBuffer ), tabletStringInternPool );
117116
118117 final int rowSize = ReadWriteIOUtils .readInt (byteBuffer );
118+ if (rowSize < 0 ) {
119+ throw new IllegalArgumentException (
120+ String .format ("Invalid row size %s in tablet format deserialization." , rowSize ));
121+ }
119122
120123 // deserialize schemas
121124 final int schemaSize =
122- BytesUtils .byteToBool (ReadWriteIOUtils .readByte (byteBuffer ))
123- ? ReadWriteIOUtils .readInt (byteBuffer )
124- : 0 ;
125+ readBooleanByte (byteBuffer , "schema existence" ) ? ReadWriteIOUtils .readInt (byteBuffer ) : 0 ;
126+ if (schemaSize < 0 ) {
127+ throw new IllegalArgumentException (
128+ String .format ("Invalid schema size %s in tablet format deserialization." , schemaSize ));
129+ }
130+ ensureRemaining (byteBuffer , schemaSize , "measurement schema existence flags" );
125131 final String [] measurement = new String [schemaSize ];
126132 final TsTableColumnCategory [] columnCategories = new TsTableColumnCategory [schemaSize ];
127133 final TSDataType [] dataTypes = new TSDataType [schemaSize ];
@@ -148,15 +154,26 @@ private static InsertTabletStatement deserializeStatementFromTabletFormat(
148154
149155 // Deserialize and calculate memory in the same loop
150156 for (int i = 0 ; i < schemaSize ; i ++) {
151- final boolean hasSchema = BytesUtils . byteToBool ( ReadWriteIOUtils . readByte ( byteBuffer ) );
157+ final boolean hasSchema = readBooleanByte ( byteBuffer , "measurement schema existence" );
152158 if (hasSchema ) {
153159 final Pair <String , TSDataType > pair = readMeasurement (byteBuffer , tabletStringInternPool );
154160 measurement [i ] = pair .getLeft ();
155161 dataTypes [i ] = pair .getRight ();
156162 if (readColumnCategory ) {
163+ if (!byteBuffer .hasRemaining ()) {
164+ throw new IllegalArgumentException (
165+ "Missing column category in current tablet format deserialization." );
166+ }
167+ final byte columnCategory = byteBuffer .get ();
168+ if (columnCategory < 0 || columnCategory >= ColumnCategory .values ().length ) {
169+ throw new IllegalArgumentException (
170+ String .format (
171+ "Invalid column category %s in current tablet format deserialization." ,
172+ columnCategory ));
173+ }
157174 columnCategories [i ] =
158175 TsTableColumnCategory .fromTsFileColumnCategory (
159- ColumnCategory .values ()[byteBuffer . get () ]);
176+ ColumnCategory .values ()[columnCategory ]);
160177 }
161178
162179 // Calculate memory for each measurement string
@@ -178,14 +195,22 @@ private static InsertTabletStatement deserializeStatementFromTabletFormat(
178195 memorySize += measurementMemorySize ;
179196 memorySize += dataTypesMemorySize ;
180197
198+ final boolean isTimesNotNull = readBooleanByte (byteBuffer , "timestamp column existence" );
199+ if (rowSize > 0 && !isTimesNotNull ) {
200+ throw new IllegalArgumentException (
201+ "Missing timestamps in tablet format deserialization with non-empty rows." );
202+ }
203+ if (isTimesNotNull ) {
204+ ensureRemaining (byteBuffer , (long ) Long .BYTES * rowSize , "timestamps" );
205+ }
206+
181207 // deserialize times and calculate memory during deserialization
182208 final long [] times = new long [rowSize ];
183209 // Calculate memory: array header + long size * rowSize
184210 final long timesMemorySize =
185211 org .apache .tsfile .utils .RamUsageEstimator .alignObjectSize (
186212 NUM_BYTES_ARRAY_HEADER + (long ) Long .BYTES * rowSize );
187213
188- final boolean isTimesNotNull = BytesUtils .byteToBool (ReadWriteIOUtils .readByte (byteBuffer ));
189214 if (isTimesNotNull ) {
190215 for (int i = 0 ; i < rowSize ; i ++) {
191216 times [i ] = ReadWriteIOUtils .readLong (byteBuffer );
@@ -199,7 +224,7 @@ private static InsertTabletStatement deserializeStatementFromTabletFormat(
199224 final BitMap [] bitMaps ;
200225 final long bitMapsMemorySize ;
201226
202- final boolean isBitMapsNotNull = BytesUtils . byteToBool ( ReadWriteIOUtils . readByte ( byteBuffer ) );
227+ final boolean isBitMapsNotNull = readBooleanByte ( byteBuffer , "bitmap column existence" );
203228 if (isBitMapsNotNull ) {
204229 // Use the method that returns both BitMap array and memory size
205230 final Pair <BitMap [], Long > bitMapsAndMemory =
@@ -218,7 +243,11 @@ private static InsertTabletStatement deserializeStatementFromTabletFormat(
218243 final Object [] values ;
219244 final long valuesMemorySize ;
220245
221- final boolean isValuesNotNull = BytesUtils .byteToBool (ReadWriteIOUtils .readByte (byteBuffer ));
246+ final boolean isValuesNotNull = readBooleanByte (byteBuffer , "value column existence" );
247+ if (rowSize > 0 && schemaSize > 0 && !isValuesNotNull ) {
248+ throw new IllegalArgumentException (
249+ "Missing values in tablet format deserialization with non-empty rows." );
250+ }
222251 if (isValuesNotNull ) {
223252 // Use the method that returns both values array and memory size
224253 final Pair <Object [], Long > valuesAndMemory =
@@ -236,7 +265,7 @@ private static InsertTabletStatement deserializeStatementFromTabletFormat(
236265 // Add values memory to total
237266 memorySize += valuesMemorySize ;
238267
239- final boolean isAligned = ReadWriteIOUtils . readBoolean (byteBuffer );
268+ final boolean isAligned = readBooleanByte (byteBuffer , "alignment" );
240269
241270 statement .setMeasurements (measurement );
242271 statement .setTimes (times );
@@ -321,6 +350,30 @@ private static void skipString(final ByteBuffer buffer) {
321350 }
322351 }
323352
353+ private static boolean readBooleanByte (final ByteBuffer buffer , final String fieldName ) {
354+ if (!buffer .hasRemaining ()) {
355+ throw new IllegalArgumentException (
356+ String .format ("Missing %s flag in tablet format deserialization." , fieldName ));
357+ }
358+
359+ final byte value = ReadWriteIOUtils .readByte (buffer );
360+ if (value != 0 && value != 1 ) {
361+ throw new IllegalArgumentException (
362+ String .format ("Invalid %s flag %s in tablet format deserialization." , fieldName , value ));
363+ }
364+ return value == 1 ;
365+ }
366+
367+ private static void ensureRemaining (
368+ final ByteBuffer buffer , final long expectedSize , final String fieldName ) {
369+ if (expectedSize > buffer .remaining ()) {
370+ throw new IllegalArgumentException (
371+ String .format (
372+ "Insufficient bytes for %s in tablet format deserialization, expected %s, remaining %s." ,
373+ fieldName , expectedSize , buffer .remaining ()));
374+ }
375+ }
376+
324377 /**
325378 * Read measurement name and data type from buffer, skipping other measurement schema fields
326379 * (encoding, compression, and tags/attributes) that are not needed for InsertTabletStatement.
@@ -364,9 +417,13 @@ private static Pair<BitMap[], Long> readBitMapsFromBufferWithMemory(
364417 boolean hasMarkedBitMap = false ;
365418
366419 for (int i = 0 ; i < columns ; i ++) {
367- final boolean hasBitMap = BytesUtils . byteToBool ( ReadWriteIOUtils . readByte ( byteBuffer ) );
420+ final boolean hasBitMap = readBooleanByte ( byteBuffer , "bitmap existence" );
368421 if (hasBitMap ) {
369422 final int size = ReadWriteIOUtils .readInt (byteBuffer );
423+ if (size < 0 ) {
424+ throw new IllegalArgumentException (
425+ String .format ("Invalid bitmap size %s in tablet format deserialization." , size ));
426+ }
370427 final Binary valueBinary = ReadWriteIOUtils .readBinary (byteBuffer );
371428 final byte [] byteArray = valueBinary .getValues ();
372429 final BitMap bitMap = new BitMap (size , byteArray );
@@ -416,8 +473,7 @@ private static Pair<Object[], Long> readValuesFromBufferWithMemory(
416473 NUM_BYTES_ARRAY_HEADER + NUM_BYTES_OBJECT_REF * columns );
417474
418475 for (int i = 0 ; i < columns ; i ++) {
419- final boolean isValueColumnsNotNull =
420- BytesUtils .byteToBool (ReadWriteIOUtils .readByte (byteBuffer ));
476+ final boolean isValueColumnsNotNull = readBooleanByte (byteBuffer , "value column existence" );
421477 if (types [i ] == null ) {
422478 continue ;
423479 }
@@ -427,7 +483,7 @@ private static Pair<Object[], Long> readValuesFromBufferWithMemory(
427483 final boolean [] boolValues = new boolean [rowSize ];
428484 if (isValueColumnsNotNull ) {
429485 for (int index = 0 ; index < rowSize ; index ++) {
430- boolValues [index ] = BytesUtils . byteToBool ( ReadWriteIOUtils . readByte ( byteBuffer ) );
486+ boolValues [index ] = readBooleanByte ( byteBuffer , "boolean value" );
431487 }
432488 }
433489 values [i ] = boolValues ;
@@ -503,8 +559,7 @@ private static Pair<Object[], Long> readValuesFromBufferWithMemory(
503559
504560 if (isValueColumnsNotNull ) {
505561 for (int index = 0 ; index < rowSize ; index ++) {
506- final boolean isNotNull =
507- BytesUtils .byteToBool (ReadWriteIOUtils .readByte (byteBuffer ));
562+ final boolean isNotNull = readBooleanByte (byteBuffer , "binary value existence" );
508563 if (isNotNull ) {
509564 binaryValues [index ] = ReadWriteIOUtils .readBinary (byteBuffer );
510565 // Calculate memory for each Binary object during deserialization
0 commit comments