Skip to content
This repository was archived by the owner on May 11, 2020. It is now read-only.

Commit f8c9745

Browse files
laizysbinet
authored andcommitted
wasm: check sections order
Fixes #144
1 parent f062133 commit f8c9745

File tree

3 files changed

+43
-13
lines changed

3 files changed

+43
-13
lines changed

wasm/internal/readpos/readpos.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ func (r *ReadPos) Read(p []byte) (int, error) {
2525
// ReadByte implements the io.ByteReader interface
2626
func (r *ReadPos) ReadByte() (byte, error) {
2727
p := make([]byte, 1)
28-
_, err := r.R.Read(p)
28+
n, err := r.R.Read(p)
29+
r.CurPos += int64(n)
2930
return p[0], err
3031
}

wasm/module.go

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package wasm
66

77
import (
88
"errors"
9+
"fmt"
910
"io"
1011
"reflect"
1112

@@ -116,15 +117,16 @@ func DecodeModule(r io.Reader) (*Module, error) {
116117
if m.Version, err = readU32(reader); err != nil {
117118
return nil, err
118119
}
120+
if m.Version != Version {
121+
return nil, fmt.Errorf("wasm: unknown binary version: %d", m.Version)
122+
}
119123

120-
for {
121-
done, err := m.readSection(reader)
122-
if err != nil {
123-
return nil, err
124-
} else if done {
125-
return m, nil
126-
}
124+
err = newSectionsReader(m).readSections(reader)
125+
if err != nil {
126+
return nil, err
127127
}
128+
129+
return m, nil
128130
}
129131

130132
// ReadModule reads a module from the reader r. resolvePath must take a string

wasm/section.go

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -105,19 +105,46 @@ func (e MissingSectionError) Error() string {
105105
return fmt.Sprintf("wasm: missing section %s", SectionID(e).String())
106106
}
107107

108+
type sectionsReader struct {
109+
lastSecOrder uint8 // previous non-custom sectionid
110+
m *Module
111+
}
112+
113+
func newSectionsReader(m *Module) *sectionsReader {
114+
return &sectionsReader{m: m}
115+
}
116+
117+
func (s *sectionsReader) readSections(r *readpos.ReadPos) error {
118+
for {
119+
done, err := s.readSection(r)
120+
switch {
121+
case err != nil:
122+
return err
123+
case done:
124+
return nil
125+
}
126+
}
127+
}
128+
108129
// reads a valid section from r. The first return value is true if and only if
109130
// the module has been completely read.
110-
func (m *Module) readSection(r *readpos.ReadPos) (bool, error) {
111-
var err error
112-
var id uint32
131+
func (sr *sectionsReader) readSection(r *readpos.ReadPos) (bool, error) {
132+
m := sr.m
113133

114134
logger.Println("Reading section ID")
115-
id, err = leb128.ReadVarUint32(r)
135+
id, err := r.ReadByte()
116136
if err == io.EOF {
117137
return true, nil
118138
} else if err != nil {
119139
return false, err
120140
}
141+
if id != uint8(SectionIDCustom) {
142+
if id <= sr.lastSecOrder {
143+
return false, fmt.Errorf("wasm: sections must occur at most once and in the prescribed order")
144+
}
145+
sr.lastSecOrder = id
146+
}
147+
121148
s := RawSection{ID: SectionID(id)}
122149

123150
logger.Println("Reading payload length")
@@ -204,7 +231,7 @@ func (m *Module) readSection(r *readpos.ReadPos) (bool, error) {
204231
return false, MissingSectionError(SectionIDFunction)
205232
}
206233
if len(m.Function.Types) != len(s.Bodies) {
207-
return false, errors.New("The number of entries in the function and code section are unequal")
234+
return false, errors.New("wasm: the number of entries in the function and code section are unequal")
208235
}
209236
if m.Types == nil {
210237
return false, MissingSectionError(SectionIDType)

0 commit comments

Comments
 (0)