Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions types/io/manifest.go
Original file line number Diff line number Diff line change
Expand Up @@ -772,20 +772,29 @@ func DecodeManifest(data []byte) (*Manifest, error) {

// Types
count := r.readUint32()
if !r.checkSliceLen(count) {
return nil, r.err
}
for i := uint32(0); i < count; i++ {
name := r.readString()
m.Types[name] = r.readType()
}

// Summaries
count = r.readUint32()
if !r.checkSliceLen(count) {
return nil, r.err
}
for i := uint32(0); i < count; i++ {
name := r.readString()
m.Summaries[name] = r.readSummary()
}

// Globals
count = r.readUint32()
if !r.checkSliceLen(count) {
return nil, r.err
}
for i := uint32(0); i < count; i++ {
name := r.readString()
m.Globals[name] = r.readType()
Expand Down
37 changes: 37 additions & 0 deletions types/io/manifest_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package io

import (
"bytes"
"errors"
"fmt"
"strings"
"testing"

"github.com/wippyai/go-lua/types/constraint"
Expand Down Expand Up @@ -237,6 +240,25 @@ func TestManifest_Encode_Decode(t *testing.T) {
}
}

func TestManifest_Encode_Decode_LargeValidManifest(t *testing.T) {
m := NewManifest(strings.Repeat("module/", 32))
for i := 0; i < 2048; i++ {
m.AddGlobal(fmt.Sprintf("global_%04d", i), typ.String)
}

data, err := m.Encode()
if err != nil {
t.Fatalf("Encode failed: %v", err)
}
decoded, err := DecodeManifest(data)
if err != nil {
t.Fatalf("DecodeManifest failed: %v", err)
}
if decoded.Path != m.Path || len(decoded.Globals) != len(m.Globals) {
t.Fatalf("decoded manifest differs: path=%q globals=%d", decoded.Path, len(decoded.Globals))
}
}

func TestManifest_EnrichedExport_DoesNotApplySummaryToNestedSameName(t *testing.T) {
m := NewManifest("test")

Expand Down Expand Up @@ -331,6 +353,21 @@ func TestDecodeManifest_InvalidMagic(t *testing.T) {
}
}

func TestDecodeManifest_RejectsCollectionLengthBeyondInput(t *testing.T) {
var buf bytes.Buffer
w := &manifestWriter{typeWriter: &typeWriter{w: &buf}}
w.writeUint32(manifestMagic)
w.writeByte(manifestVersion)
w.writeUint64(0)
w.writeString("test")
w.writeBool(false)
w.writeUint32(1024)

if _, err := DecodeManifest(buf.Bytes()); !errors.Is(err, ErrCorruptedData) {
t.Fatalf("DecodeManifest error = %v", err)
}
}

func TestApplyFunctionSummary_Nil(t *testing.T) {
fn := typ.Func().Build()
result := ApplyFunctionSummary(fn, nil)
Expand Down
10 changes: 6 additions & 4 deletions types/io/reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ import (
"github.com/wippyai/go-lua/types/typ"
)

const maxTypeDepth = 32
const maxTypeNodes = 1024
const maxTypeDepth = 256
const maxTypeNodes = 1 << 20
const maxCollectionLen = 1 << 20
const maxStringLen = 16 << 20

type typeReader struct {
r *bytes.Reader
Expand Down Expand Up @@ -71,7 +73,7 @@ func (r *typeReader) readString() string {
return ""
}

if length > maxSliceLen {
if length > maxStringLen || uint64(length) > uint64(r.r.Len()) {
r.err = ErrCorruptedData
return ""
}
Expand All @@ -87,7 +89,7 @@ func (r *typeReader) readBool() bool {
}

func (r *typeReader) checkSliceLen(n uint32) bool {
if n > maxSliceLen {
if n > maxCollectionLen || uint64(n) > uint64(r.r.Len()) {
r.err = ErrCorruptedData
return false
}
Expand Down
2 changes: 0 additions & 2 deletions types/io/serialize.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,6 @@ var (
ErrCorruptedData = errors.New("corrupted type data")
)

const maxSliceLen = 64

const (
annotationArgNil byte = iota
annotationArgString
Expand Down
11 changes: 11 additions & 0 deletions types/io/serialize_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1397,6 +1397,17 @@ func TestDecode_ReadString_Empty(t *testing.T) {
}
}

func TestDecode_ReadString_RejectsLengthBeyondInput(t *testing.T) {
var buf bytes.Buffer
tw := &typeWriter{w: &buf}
tw.writeUint32(1024)

r := &typeReader{r: bytes.NewReader(buf.Bytes())}
if got := r.readString(); got != "" || !errors.Is(r.err, ErrCorruptedData) {
t.Fatalf("readString() = %q, err=%v", got, r.err)
}
}

func TestDecode_Literal_UnknownBase(t *testing.T) {
// kind.Literal is 23 (0x17)
var buf bytes.Buffer
Expand Down