From 89b4a18cee9a2be4f832f2ad4b56575d627d22d8 Mon Sep 17 00:00:00 2001 From: "Victor M. Alvarez" Date: Thu, 12 Sep 2024 12:07:21 +0200 Subject: [PATCH] refactor: make `Metadata.Identifier` and `Metadata.Value` methods instead of fields. Also fixes a nil pointer dereference when a rule doesn't have any metadata. --- go/compiler_test.go | 17 +++++++++++++++-- go/main.go | 33 +++++++++++++++++++++++++-------- go/scanner_test.go | 36 ++++++++++++++++++------------------ 3 files changed, 58 insertions(+), 28 deletions(-) diff --git a/go/compiler_test.go b/go/compiler_test.go index b0792890..b0c335b9 100644 --- a/go/compiler_test.go +++ b/go/compiler_test.go @@ -149,10 +149,18 @@ func TestRulesIter(t *testing.T) { c, err := NewCompiler() assert.NoError(t, err) - c.AddSource("rule test_1 { condition: true }") + c.AddSource(`rule test_1 { + condition: + true + }`) assert.NoError(t, err) - c.AddSource("rule test_2 { condition: true }") + c.AddSource(`rule test_2 { + meta: + foo = "foo" + condition: + true + }`) assert.NoError(t, err) rules := c.Build() @@ -162,6 +170,11 @@ func TestRulesIter(t *testing.T) { assert.Len(t, slice, 2) assert.Equal(t, "test_1", slice[0].Identifier()) assert.Equal(t, "test_2", slice[1].Identifier()) + + assert.Len(t, slice[0].Metadata(), 0) + assert.Len(t, slice[1].Metadata(), 1) + + assert.Equal(t, "foo", slice[1].Metadata()[0].Identifier()) } func TestWarnings(t *testing.T) { diff --git a/go/main.go b/go/main.go index aa795c22..2c5abaf4 100644 --- a/go/main.go +++ b/go/main.go @@ -205,28 +205,35 @@ func (r *Rule) Metadata() []Metadata { return r.metadata } + // if cMetadata is nil the rule doesn't have any metadata, return an + // empty list. + if r.cMetadata == nil { + r.metadata = make([]Metadata, 0) + return r.metadata + } + numMetadata := int(r.cMetadata.num_entries) cMetadata := unsafe.Slice(r.cMetadata.entries, numMetadata) r.metadata = make([]Metadata, numMetadata) for i, metadata := range cMetadata { - r.metadata[i].Identifier = C.GoString(metadata.identifier) + r.metadata[i].identifier = C.GoString(metadata.identifier) switch metadata.value_type { case C.I64: - r.metadata[i].Value = int64( + r.metadata[i].value = int64( C.meta_i64(unsafe.Pointer(&metadata.value))) case C.F64: - r.metadata[i].Value = float64( + r.metadata[i].value = float64( C.meta_f64(unsafe.Pointer(&metadata.value))) case C.BOOLEAN: - r.metadata[i].Value = bool( + r.metadata[i].value = bool( C.meta_bool(unsafe.Pointer(&metadata.value))) case C.STRING: - r.metadata[i].Value = C.GoString( + r.metadata[i].value = C.GoString( C.meta_str(unsafe.Pointer(&metadata.value))) case C.BYTES: bytes := C.meta_bytes(unsafe.Pointer(&metadata.value)) - r.metadata[i].Value = C.GoBytes( + r.metadata[i].value = C.GoBytes( unsafe.Pointer(bytes.data), C.int(bytes.length), ) @@ -238,8 +245,18 @@ func (r *Rule) Metadata() []Metadata { // Metadata represents a metadata in a Rule. type Metadata struct { - Identifier string - Value interface{} + identifier string + value interface{} +} + +// Identifier associated to the metadata. +func (m *Metadata) Identifier() string { + return m.identifier +} + +// Value associated to the metadata. +func (m *Metadata) Value() interface{} { + return m.value } // Patterns returns the patterns defined by this rule. diff --git a/go/scanner_test.go b/go/scanner_test.go index e79cf0a8..60a76a06 100644 --- a/go/scanner_test.go +++ b/go/scanner_test.go @@ -85,29 +85,29 @@ func TestScannerTimeout(t *testing.T) { } func TestScannerMetadata(t *testing.T) { - r, _ := Compile(`rule t { - meta: - some_int = 1 - some_float = 2.3034 - some_bool = true - some_string = "hello" + r, _ := Compile(`rule t { + meta: + some_int = 1 + some_float = 2.3034 + some_bool = true + some_string = "hello" some_bytes = "\x00\x01\x02" - condition: - true + condition: + true }`) s := NewScanner(r) scanResults, _ := s.Scan([]byte{}) matchingRules := scanResults.MatchingRules() assert.Len(t, matchingRules, 1) - assert.Equal(t, "some_int", matchingRules[0].Metadata()[0].Identifier) - assert.Equal(t, int64(1), matchingRules[0].Metadata()[0].Value) - assert.Equal(t, "some_float", matchingRules[0].Metadata()[1].Identifier) - assert.Equal(t, float64(2.3034), matchingRules[0].Metadata()[1].Value) - assert.Equal(t, "some_bool", matchingRules[0].Metadata()[2].Identifier) - assert.Equal(t, true, matchingRules[0].Metadata()[2].Value) - assert.Equal(t, "some_string", matchingRules[0].Metadata()[3].Identifier) - assert.Equal(t, "hello", matchingRules[0].Metadata()[3].Value) - assert.Equal(t, "some_bytes", matchingRules[0].Metadata()[4].Identifier) - assert.Equal(t, []byte{0, 1, 2}, matchingRules[0].Metadata()[4].Value) + assert.Equal(t, "some_int", matchingRules[0].Metadata()[0].Identifier()) + assert.Equal(t, int64(1), matchingRules[0].Metadata()[0].Value()) + assert.Equal(t, "some_float", matchingRules[0].Metadata()[1].Identifier()) + assert.Equal(t, float64(2.3034), matchingRules[0].Metadata()[1].Value()) + assert.Equal(t, "some_bool", matchingRules[0].Metadata()[2].Identifier()) + assert.Equal(t, true, matchingRules[0].Metadata()[2].Value()) + assert.Equal(t, "some_string", matchingRules[0].Metadata()[3].Identifier()) + assert.Equal(t, "hello", matchingRules[0].Metadata()[3].Value()) + assert.Equal(t, "some_bytes", matchingRules[0].Metadata()[4].Identifier()) + assert.Equal(t, []byte{0, 1, 2}, matchingRules[0].Metadata()[4].Value()) }