From 8141a137ba50b553a9da877d95c7ccb491d041c6 Mon Sep 17 00:00:00 2001 From: Nikita Pivkin Date: Wed, 5 Jun 2024 10:20:54 +0700 Subject: [PATCH] fix(misconf): parsing numbers without fraction as int (#6834) --- .../cloudformation/parser/intrinsics.go | 2 +- .../cloudformation/parser/parameter.go | 19 +++++++- .../cloudformation/parser/parser_test.go | 47 +++++++++++++++++++ .../scanners/cloudformation/parser/util.go | 16 +++++-- 4 files changed, 79 insertions(+), 5 deletions(-) diff --git a/pkg/iac/scanners/cloudformation/parser/intrinsics.go b/pkg/iac/scanners/cloudformation/parser/intrinsics.go index 1dadc4f6d6fd..cda2bde29e41 100644 --- a/pkg/iac/scanners/cloudformation/parser/intrinsics.go +++ b/pkg/iac/scanners/cloudformation/parser/intrinsics.go @@ -100,7 +100,7 @@ func getIntrinsicTag(tag string) string { } } -func abortIntrinsic(property *Property, msg string, components ...string) (*Property, bool) { +func abortIntrinsic(property *Property, _ string, _ ...string) (*Property, bool) { // return property, false } diff --git a/pkg/iac/scanners/cloudformation/parser/parameter.go b/pkg/iac/scanners/cloudformation/parser/parameter.go index 671058a9f83c..20e2011417d5 100644 --- a/pkg/iac/scanners/cloudformation/parser/parameter.go +++ b/pkg/iac/scanners/cloudformation/parser/parameter.go @@ -27,7 +27,24 @@ func (p *Parameter) UnmarshalYAML(node *yaml.Node) error { } func (p *Parameter) UnmarshalJSONWithMetadata(node jfather.Node) error { - return node.Decode(&p.inner) + + var inner parameterInner + + if err := node.Decode(&inner); err != nil { + return err + } + + // jfather parses Number without fraction as int64 + // https://github.com/liamg/jfather/blob/4ef05d70c05af167226d3333a4ec7d8ac3c9c281/parse_number.go#L33-L42 + switch v := inner.Default.(type) { + case int64: + inner.Default = int(v) + default: + inner.Default = v + } + + p.inner = inner + return nil } func (p *Parameter) Type() cftypes.CfType { diff --git a/pkg/iac/scanners/cloudformation/parser/parser_test.go b/pkg/iac/scanners/cloudformation/parser/parser_test.go index 1c5688b7fa55..396e12f1bf57 100644 --- a/pkg/iac/scanners/cloudformation/parser/parser_test.go +++ b/pkg/iac/scanners/cloudformation/parser/parser_test.go @@ -370,5 +370,52 @@ Resources: assert.Equal(t, "testbucket", bucketNameProp.AsString()) } } +} + +func TestJsonWithNumbers(t *testing.T) { + src := ` +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Parameters": { + "SomeIntParam": { + "Type": "Number", + "Default": 1 + }, + "SomeFloatParam": { + "Type": "Number", + "Default": 1.1 + } + }, + "Resources": { + "SomeResource": { + "Type": "Test::Resource", + "Properties": { + "SomeIntProp": 1, + "SomeFloatProp": 1.1 + } + } + } +} +` + + fsys := testutil.CreateFS(t, map[string]string{ + "main.json": src, + }) + + files, err := New().ParseFS(context.TODO(), fsys, ".") + + require.NoError(t, err) + require.Len(t, files, 1) + + file := files[0] + + assert.Equal(t, 1, file.Parameters["SomeIntParam"].Default()) + assert.Equal(t, 1.1, file.Parameters["SomeFloatParam"].Default()) + + res := file.GetResourcesByType("Test::Resource") + assert.NotNil(t, res) + assert.Len(t, res, 1) + assert.Equal(t, 1, res[0].GetProperty("SomeIntProp").AsIntValue().Value()) + assert.Equal(t, 0, res[0].GetProperty("SomeFloatProp").AsIntValue().Value()) } diff --git a/pkg/iac/scanners/cloudformation/parser/util.go b/pkg/iac/scanners/cloudformation/parser/util.go index 03b9bf8da837..5ee61de17b9d 100644 --- a/pkg/iac/scanners/cloudformation/parser/util.go +++ b/pkg/iac/scanners/cloudformation/parser/util.go @@ -13,10 +13,20 @@ import ( func setPropertyValueFromJson(node jfather.Node, propertyData *PropertyInner) error { switch node.Kind() { - case jfather.KindNumber: - propertyData.Type = cftypes.Float64 - return node.Decode(&propertyData.Value) + var val any + if err := node.Decode(&val); err != nil { + return err + } + switch v := val.(type) { + case float64: + propertyData.Type = cftypes.Float64 + propertyData.Value = v + case int64: + propertyData.Type = cftypes.Int + propertyData.Value = int(v) + } + return nil case jfather.KindBoolean: propertyData.Type = cftypes.Bool return node.Decode(&propertyData.Value)