From 453f44e4c55d034f8e1176069b69df0faa590435 Mon Sep 17 00:00:00 2001 From: "liron.levin" Date: Wed, 23 Oct 2024 10:20:37 +0300 Subject: [PATCH] Fix panic in `buildCodecForTypeDescribedByString` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit scale attribute is optional in schema: ``` The following attributes are supported: • scale, a JSON integer representing the scale (optional). If not specified the scale is 0. • precision, a JSON integer representing the (maximum) precision of decimals stored in this type (required) ``` If it's missing from format, code will panic on ``` panic: interface conversion: interface {} is nil, not float64 ``` Ensure code robustness and verify both values are cast-able to float64. --- codec.go | 6 ++++-- codec_test.go | 8 ++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/codec.go b/codec.go index 9406ddb..82eeb37 100644 --- a/codec.go +++ b/codec.go @@ -668,11 +668,13 @@ func buildCodecForTypeDescribedByString(st map[string]*Codec, enclosingNamespace // For "bytes.decimal" types verify that the scale and precision in this schema map match a cached codec before // using the cached codec in favor of creating a new codec. if searchType == "bytes.decimal" { + precision, ok1 := schemaMap["precision"].(float64) + scale, ok2 := schemaMap["scale"].(float64) // Search the cached codecs for a "bytes.decimal" codec with a "precision" and "scale" specified in the key, // only if that matches return the cached codec. Otherwise, create a new codec for this "bytes.decimal". - decimalSearchType := fmt.Sprintf("bytes.decimal.%d.%d", int(schemaMap["precision"].(float64)), int(schemaMap["scale"].(float64))) - if cd2, ok := st[decimalSearchType]; ok { + decimalSearchType := fmt.Sprintf("bytes.decimal.%d.%d", int(precision), int(scale)) + if cd2, ok := st[decimalSearchType]; ok && ok1 && ok2 { return cd2, nil } diff --git a/codec_test.go b/codec_test.go index bafe51c..7854578 100644 --- a/codec_test.go +++ b/codec_test.go @@ -408,4 +408,12 @@ func Test_buildCodecForTypeDescribedByString_CacheRespectsPrecisionScale(t *test if cacheMiss.schemaOriginal == cachedCodecIdentifier { t.Errorf("GOT: %v; WANT: %v", cacheMiss.schemaOriginal, "!= "+cachedCodecIdentifier) } + + // Scale does not exist in schema, so cache miss + delete(schemaMap, "scale") + cacheMiss, err = buildCodecForTypeDescribedByString(cache, "", "bytes", schemaMap, nil) + ensureError(t, err) + if cacheMiss.schemaOriginal == cachedCodecIdentifier { + t.Errorf("GOT: %v; WANT: %v", cacheMiss.schemaOriginal, "!= "+cachedCodecIdentifier) + } }