CVE-2023-37186: NULL Pointer Dereference (CWE-476)
value: C-blosc2 before 2.9.3 was discovered to contain a NULL pointer dereference in ndlz/ndlz8x8.c via a NULL pointer to memset.
CWE description: The product dereferences a pointer that it expects to be valid but is NULL.
CVSS v3 base score: 7.5
Published: 2023-12-25T07:15Z
Repository: https://github.com/Blosc/c-blosc2
Language: C
Files changed: plugins/codecs/ndlz/ndlz4x4.c, plugins/codecs/ndlz/ndlz8x8.c
Commit date: 2023-06-21 11:17:51 +0200
Commit message: Fix #522

Diff: diff --git a/plugins/codecs/ndlz/ndlz4x4.c b/plugins/codecs/ndlz/ndlz4x4.c
index d38cde89..60e0813b 100644
--- a/plugins/codecs/ndlz/ndlz4x4.c
+++ b/plugins/codecs/ndlz/ndlz4x4.c
@@ -57,10 +57,12 @@
 
 
 int ndlz4_compress(const uint8_t *input, int32_t input_len, uint8_t *output, int32_t output_len,
                    uint8_t meta, blosc2_cparams *cparams) {
   BLOSC_UNUSED_PARAM(meta);
+  BLOSC_ERROR_NULL(cparams, BLOSC2_ERROR_NULL_POINTER);
+  BLOSC_ERROR_NULL(cparams->schunk, BLOSC2_ERROR_NULL_POINTER);
   uint8_t *smeta;
   int32_t smeta_len;
 
   if (blosc2_meta_get(cparams->schunk, "b2nd", &smeta, &smeta_len) < 0) {
     BLOSC_TRACE_ERROR("b2nd layer not found!");
@@ -511,10 +513,12 @@ static unsigned char* copy_match_16(unsigned char *op, const unsigned char *matc
 
 int ndlz4_decompress(const uint8_t *input, int32_t input_len, uint8_t *output, int32_t output_len,
                      uint8_t meta, blosc2_dparams *dparams) {
   BLOSC_UNUSED_PARAM(meta);
   BLOSC_UNUSED_PARAM(dparams);
+  BLOSC_ERROR_NULL(input, BLOSC2_ERROR_NULL_POINTER);
+  BLOSC_ERROR_NULL(output, BLOSC2_ERROR_NULL_POINTER);
 
   uint8_t *ip = (uint8_t *) input;
   uint8_t *ip_limit = ip + input_len;
   uint8_t *op = (uint8_t *) output;
   uint8_t ndim;
@@ -539,11 +543,11 @@ int ndlz4_decompress(const uint8_t *input, int32_t input_len, uint8_t *output, i
   memcpy(&blockshape[1], ip, 4);
   ip += 4;
   eshape[0] = ((blockshape[0] + 3) / 4) * 4;
   eshape[1] = ((blockshape[1] + 3) / 4) * 4;
 
-  if (NDLZ_UNEXPECT_CONDITIONAL(output_len < (int32_t) (blockshape[0] * blockshape[1]))) {
+  if (NDLZ_UNEXPECT_CONDITIONAL((int64_t)output_len < (int64_t)blockshape[0] * (int64_t)blockshape[1])) {
     return 0;
   }
   memset(op, 0, blockshape[0] * blockshape[1]);
 
   uint32_t i_stop[2];
diff --git a/plugins/codecs/ndlz/ndlz8x8.c b/plugins/codecs/ndlz/ndlz8x8.c
index 07ef5ade..59f63ab7 100644
--- a/plugins/codecs/ndlz/ndlz8x8.c
+++ b/plugins/codecs/ndlz/ndlz8x8.c
@@ -57,10 +57,12 @@
 
 
 int ndlz8_compress(const uint8_t *input, int32_t input_len, uint8_t *output, int32_t output_len,
                    uint8_t meta, blosc2_cparams *cparams) {
   BLOSC_UNUSED_PARAM(meta);
+  BLOSC_ERROR_NULL(cparams, BLOSC2_ERROR_NULL_POINTER);
+  BLOSC_ERROR_NULL(cparams->schunk, BLOSC2_ERROR_NULL_POINTER);
   uint8_t *smeta;
   int32_t smeta_len;
 
   if (blosc2_meta_get(cparams->schunk, "b2nd", &smeta, &smeta_len) < 0) {
     BLOSC_TRACE_ERROR("b2nd layer not found!");
@@ -428,10 +430,12 @@ static unsigned char* copy_match_16(unsigned char *op, const unsigned char *matc
 
 int ndlz8_decompress(const uint8_t *input, int32_t input_len, uint8_t *output, int32_t output_len,
                      uint8_t meta, blosc2_dparams *dparams) {
   BLOSC_UNUSED_PARAM(meta);
   BLOSC_UNUSED_PARAM(dparams);
+  BLOSC_ERROR_NULL(input, BLOSC2_ERROR_NULL_POINTER);
+  BLOSC_ERROR_NULL(output, BLOSC2_ERROR_NULL_POINTER);
 
   const int cell_shape = 8;
   const int cell_size = 64;
   uint8_t *ip = (uint8_t *) input;
   uint8_t *ip_limit = ip + input_len;
@@ -456,12 +460,11 @@ int ndlz8_decompress(const uint8_t *input, int32_t input_len, uint8_t *output, i
   ip += 4;
   memcpy(&blockshape[1], ip, 4);
   ip += 4;
   eshape[0] = ((blockshape[0] + 7) / cell_shape) * cell_shape;
   eshape[1] = ((blockshape[1] + 7) / cell_shape) * cell_shape;
-
-  if (NDLZ_UNEXPECT_CONDITIONAL(output_len < blockshape[0] * blockshape[1])) {
+  if (NDLZ_UNEXPECT_CONDITIONAL((int64_t)output_len < (int64_t)blockshape[0] * (int64_t)blockshape[1])) {
     return 0;
   }
   memset(op, 0, blockshape[0] * blockshape[1]);
 
   int32_t i_stop[2];

Vulnerable code:   if (NDLZ_UNEXPECT_CONDITIONAL(output_len < (int32_t) (blockshape[0] * blockshape[1]))) {

  if (NDLZ_UNEXPECT_CONDITIONAL(output_len < blockshape[0] * blockshape[1])) {
Fixed code:   BLOSC_ERROR_NULL(cparams, BLOSC2_ERROR_NULL_POINTER);
  BLOSC_ERROR_NULL(cparams->schunk, BLOSC2_ERROR_NULL_POINTER);
  BLOSC_ERROR_NULL(input, BLOSC2_ERROR_NULL_POINTER);
  BLOSC_ERROR_NULL(output, BLOSC2_ERROR_NULL_POINTER);
  if (NDLZ_UNEXPECT_CONDITIONAL((int64_t)output_len < (int64_t)blockshape[0] * (int64_t)blockshape[1])) {
  BLOSC_ERROR_NULL(cparams, BLOSC2_ERROR_NULL_POINTER);
  BLOSC_ERROR_NULL(cparams->schunk, BLOSC2_ERROR_NULL_POINTER);
  BLOSC_ERROR_NULL(input, BLOSC2_ERROR_NULL_POINTER);
  BLOSC_ERROR_NULL(output, BLOSC2_ERROR_NULL_POINTER);
  if (NDLZ_UNEXPECT_CONDITIONAL((int64_t)output_len < (int64_t)blockshape[0] * (int64_t)blockshape[1])) {