11/*
2- Copyright (c) 2012-2021,2023, 2025 Genome Research Ltd.
2+ Copyright (c) 2012-2021,2023, 2025, 2026 Genome Research Ltd.
33Author: James Bonfield <jkb@sanger.ac.uk>
44
55Redistribution and use in source and binary forms, with or without
@@ -776,17 +776,23 @@ cram_codec *cram_varint_decode_init(cram_block_compression_hdr *hdr,
776776 // does not change.
777777 switch (codec ) {
778778 case E_VARINT_UNSIGNED :
779- c -> decode = (option == E_INT )
780- ? cram_varint_decode_int
781- : cram_varint_decode_long ;
779+ if (option == E_INT || option == E_SINT )
780+ c -> decode = cram_varint_decode_int ;
781+ else if (option == E_LONG || option == E_SLONG )
782+ c -> decode = cram_varint_decode_long ;
783+ else
784+ goto malformed ;
782785 break ;
783786 case E_VARINT_SIGNED :
784- c -> decode = (option == E_INT )
785- ? cram_varint_decode_sint
786- : cram_varint_decode_slong ;
787+ if (option == E_INT || option == E_SINT )
788+ c -> decode = cram_varint_decode_sint ;
789+ else if (option == E_LONG || option == E_SLONG )
790+ c -> decode = cram_varint_decode_slong ;
791+ else
792+ goto malformed ;
787793 break ;
788794 default :
789- return NULL ;
795+ goto malformed ;
790796 }
791797
792798 c -> free = cram_varint_decode_free ;
@@ -798,14 +804,17 @@ cram_codec *cram_varint_decode_init(cram_block_compression_hdr *hdr,
798804 c -> u .varint .offset = vv -> varint_get64s (& cp , cp_end , NULL );
799805
800806 if (cp - data != size ) {
801- fprintf (stderr , "Malformed varint header stream\n" );
802- free (c );
803- return NULL ;
807+ goto malformed ;
804808 }
805809
806810 c -> u .varint .type = option ;
807811
808812 return c ;
813+
814+ malformed :
815+ hts_log_error ("Malformed varint header stream" );
816+ free (c );
817+ return NULL ;
809818}
810819
811820int cram_varint_encode_int (cram_slice * slice , cram_codec * c ,
@@ -924,6 +933,9 @@ int cram_const_decode_byte(cram_slice *slice, cram_codec *c,
924933 cram_block * in , char * out , int * out_size ) {
925934 int i , n ;
926935
936+ if (!out )
937+ return 0 ;
938+
927939 for (i = 0 , n = * out_size ; i < n ; i ++ )
928940 out [i ] = c -> u .xconst .val ;
929941
@@ -978,12 +990,17 @@ cram_codec *cram_const_decode_init(cram_block_compression_hdr *hdr,
978990 return NULL ;
979991
980992 c -> codec = codec ;
981- if (codec == E_CONST_BYTE )
993+ if (codec == E_CONST_BYTE && option == E_BYTE )
982994 c -> decode = cram_const_decode_byte ;
983- else if (option == E_INT )
995+ else if (codec == E_CONST_INT && ( option == E_INT || option == E_SINT ) )
984996 c -> decode = cram_const_decode_int ;
985- else
997+ else if ( codec == E_CONST_INT && ( option == E_LONG || option == E_SLONG ))
986998 c -> decode = cram_const_decode_long ;
999+ else {
1000+ hts_log_error ("Malformed const header stream" );
1001+ free (c );
1002+ return NULL ;
1003+ }
9871004 c -> free = cram_const_decode_free ;
9881005 c -> size = cram_const_decode_size ;
9891006 c -> get_block = NULL ;
@@ -1404,7 +1421,7 @@ int cram_xpack_decode_char(cram_slice *slice, cram_codec *c, cram_block *in, cha
14041421 if (out )
14051422 memcpy (out , b -> data + b -> byte , * out_size );
14061423 b -> byte += * out_size ;
1407- } else {
1424+ } else if ( out ) {
14081425 memset (out , c -> u .xpack .rmap [0 ], * out_size );
14091426 }
14101427
@@ -2111,7 +2128,8 @@ int cram_xrle_decode_char(cram_slice *slice, cram_codec *c, cram_block *in, char
21112128 cram_xrle_decode_expand_char (slice , c );
21122129 cram_block * b = slice -> block_by_id [512 + c -> codec_id ];
21132130
2114- memcpy (out , b -> data + b -> idx , n );
2131+ if (out )
2132+ memcpy (out , b -> data + b -> idx , n );
21152133 b -> idx += n ;
21162134 return 0 ;
21172135
@@ -3357,14 +3375,19 @@ int cram_byte_array_len_decode(cram_slice *slice, cram_codec *c,
33573375 int32_t len = 0 , one = 1 ;
33583376 int r ;
33593377
3360- r = c -> u .byte_array_len .len_codec -> decode (slice , c -> u .byte_array_len .len_codec ,
3361- in , (char * )& len , & one );
3362- //printf("ByteArray Len=%d\n", len);
3378+ cram_codec * len_codec = c -> u .byte_array_len .len_codec ;
3379+ cram_codec * val_codec = c -> u .byte_array_len .val_codec ;
33633380
3364- if (!r && c -> u .byte_array_len .val_codec && len >= 0 ) {
3365- r = c -> u .byte_array_len .val_codec -> decode (slice ,
3366- c -> u .byte_array_len .val_codec ,
3367- in , out , & len );
3381+ r = len_codec -> decode (slice , len_codec , in , (char * )& len , & one );
3382+ if (len < 0 || (len > * out_size &&
3383+ !(val_codec -> codec == E_EXTERNAL &&
3384+ val_codec -> u .external .type == E_BYTE_ARRAY_BLOCK ))) {
3385+ fprintf (stderr , "Error: overflow in cram_byte_array_len_decode.\n" );
3386+ return -1 ;
3387+ }
3388+
3389+ if (!r && val_codec ) {
3390+ r = val_codec -> decode (slice , val_codec , in , out , & len );
33683391 } else {
33693392 return -1 ;
33703393 }
@@ -3563,7 +3586,7 @@ cram_codec *cram_byte_array_len_encode_init(cram_stats *st,
35633586static int cram_byte_array_stop_decode_char (cram_slice * slice , cram_codec * c ,
35643587 cram_block * in , char * out ,
35653588 int * out_size ) {
3566- char * cp , ch ;
3589+ uint8_t * cp ;
35673590 cram_block * b = NULL ;
35683591
35693592 b = cram_get_block_by_id (slice , c -> u .byte_array_stop .content_id );
@@ -3573,31 +3596,29 @@ static int cram_byte_array_stop_decode_char(cram_slice *slice, cram_codec *c,
35733596 if (b -> idx >= b -> uncomp_size )
35743597 return -1 ;
35753598
3576- cp = (char * )b -> data + b -> idx ;
3599+ ssize_t term = b -> uncomp_size - b -> idx ;
3600+ cp = b -> data + b -> idx ;
35773601 if (out ) {
35783602 // memccpy equivalent but without copying the terminating byte
3579- ssize_t term = MIN (* out_size , b -> uncomp_size - b -> idx );
3580- while ((ch = * cp ) != (char )c -> u .byte_array_stop .stop ) {
3581- if (term -- < 0 )
3582- break ;
3583- * out ++ = ch ;
3584- cp ++ ;
3603+ if (term > * out_size )
3604+ term = * out_size ;
3605+ while (-- term >= 0 && * cp != c -> u .byte_array_stop .stop ) {
3606+ * out ++ = * cp ++ ;
35853607 }
35863608
3587- // Attempted overrun on input or output
3588- if (ch != (char )c -> u .byte_array_stop .stop )
3589- return -1 ;
35903609 } else {
35913610 // Consume input, but produce no output
3592- while ((ch = * cp ) != (char )c -> u .byte_array_stop .stop ) {
3593- if (cp - (char * )b -> data >= b -> uncomp_size )
3594- return -1 ;
3611+ while (-- term >= 0 && * cp != c -> u .byte_array_stop .stop ) {
35953612 cp ++ ;
35963613 }
35973614 }
35983615
3599- * out_size = cp - (char * )(b -> data + b -> idx );
3600- b -> idx = cp - (char * )b -> data + 1 ;
3616+ // Attempted overrun on input or output
3617+ if (cp >= b -> data + b -> uncomp_size || * cp != c -> u .byte_array_stop .stop )
3618+ return -1 ;
3619+
3620+ * out_size = cp - (b -> data + b -> idx );
3621+ b -> idx = cp - b -> data + 1 ;
36013622
36023623 return 0 ;
36033624}
0 commit comments