Example #1
1
func (uls UnknownLoaders) Load(r reader.Reader, payloadLen uint32) (err error) {
	defer func() {
		err = errutil.ErrorOrPanic(recover())
	}()

	load := loader.L{r}

	nameLen := load.Varuint32()
	if nameLen > maxSectionNameLen {
		panic(errors.New("unknown section name is too long"))
	}

	name := string(load.Bytes(nameLen))

	if f := uls[name]; f != nil {
		if err := f(name, load); err != nil {
			panic(err)
		}
	} else {
		if _, err := io.CopyN(ioutil.Discard, load, int64(payloadLen)); err != nil {
			panic(err)
		}
	}

	return
}
Example #2
1
File: names.go Project: tsavola/wag
func (ns *NameSection) Load(_ string, r reader.Reader) (err error) {
	defer func() {
		err = errutil.ErrorOrPanic(recover())
	}()

	load := loader.L{r}

	count := load.Varuint32()
	ns.FunctionNames = make([]FunctionName, count)

	for i := range ns.FunctionNames {
		fn := &ns.FunctionNames[i]

		funNameLen := load.Varuint32()
		fn.FunName = string(load.Bytes(funNameLen))

		localCount := load.Varuint32()
		fn.LocalNames = make([]string, localCount)

		for j := range fn.LocalNames {
			localNameLen := load.Varuint32()
			fn.LocalNames[j] = string(load.Bytes(localNameLen))
		}
	}

	return
}
Example #3
0
File: data.go Project: tsavola/wag
func (m *Module) genData(load loader.L) {
	if debug {
		debugf("data section")
		debugDepth++
	}

	if m.memoryOffset&15 != 0 {
		// not 16-byte aligned?  (assume at least 8-byte alignment.)
		n := len(m.globals)
		m.globals = append(m.globals, global{})
		m.data = appendGlobalsData(m.data, m.globals[n:])
		m.memoryOffset = len(m.data)
	}

	for i := range load.Count() {
		if debug {
			debugf("data segment")
			debugDepth++
		}

		if index := load.Varuint32(); index != 0 {
			panic(fmt.Errorf("unsupported memory index: %d", index))
		}

		offset := readOffsetInitExpr(load, m)

		size := load.Varuint32()

		needMemorySize := int64(offset) + int64(size)
		if needMemorySize >= int64(m.memoryLimits.initial) {
			panic(fmt.Errorf("memory segment #%d exceeds initial memory size", i))
		}

		needDataSize := int64(m.memoryOffset) + needMemorySize
		if needDataSize > int64(len(m.data)) {
			if int64(cap(m.data)) >= needDataSize {
				m.data = m.data[:needDataSize]
			} else {
				buf := make([]byte, needDataSize)
				copy(buf, m.data)
				m.data = buf
			}
		}

		dataOffset := m.memoryOffset + int(offset)
		load.Into(m.data[dataOffset:needDataSize])

		if debug {
			debugDepth--
			debugf("data segmented: offset=0x%x size=0x%x", offset, size)
		}
	}

	if debug {
		debugDepth--
		debugf("data sectioned")
	}
}
Example #4
0
func readSectionHeader(load loader.L, expectId byte, idError string) (ok bool) {
	id, err := load.ReadByte()
	if err != nil {
		if err == io.EOF {
			return
		}
		panic(err)
	}

	if id != expectId {
		panic(errors.New(idError))
	}

	load.Varuint32() // payload len

	ok = true
	return
}
Example #5
0
File: copy.go Project: tsavola/wag
func copySection(w io.Writer, r reader.Reader, expectId byte) (ok bool) {
	store := storer{w}
	load := loader.L{Reader: r}

loop:
	for {
		id, err := load.ReadByte()
		if err != nil {
			if err == io.EOF {
				return
			}
			panic(err)
		}

		switch {
		case id == sectionids.Unknown:
			payloadLen := load.Varuint32()
			if _, err := io.CopyN(ioutil.Discard, load, int64(payloadLen)); err != nil {
				panic(err)
			}

		case id == expectId:
			store.Byte(id)
			break loop

		default:
			load.UnreadByte()
			return
		}
	}

	payloadLen := load.Varuint32()
	store.Varuint32(payloadLen)

	if _, err := io.CopyN(store, load, int64(payloadLen)); err != nil {
		panic(err)
	}

	ok = true
	return
}
Example #6
0
func readResizableLimits(load loader.L, maxInitial, maxMaximum uint32, scale int) resizableLimits {
	flags := load.Varuint32()

	initial := load.Varuint32()
	if initial > maxInitial {
		panic(fmt.Errorf("initial memory size is too large: %d", initial))
	}

	maximum := maxMaximum

	if (flags & resizableLimitsFlagMaximum) != 0 {
		maximum = load.Varuint32()
		if maximum > maxMaximum {
			maximum = maxMaximum
		}
		if maximum < initial {
			panic(fmt.Errorf("maximum memory size %d is smaller than initial memory size %d", maximum, initial))
		}
	}

	return resizableLimits{int(initial) * scale, int(maximum) * scale, true}
}
Example #7
0
func (m moduleLoader) loadUntil(load loader.L, untilSection byte) byte {
	var header struct {
		MagicNumber uint32
		Version     uint32
	}
	if err := binary.Read(load, binary.LittleEndian, &header); err != nil {
		panic(err)
	}
	if header.MagicNumber != moduleMagicNumber {
		panic(errors.New("not a WebAssembly module"))
	}
	if header.Version != moduleVersion {
		panic(fmt.Errorf("unsupported module version: %d", header.Version))
	}

	var skipSection func(byte, uint32) error

	if m.UnknownSectionLoader != nil {
		skipSection = func(id byte, payloadLen uint32) (err error) {
			if id == sectionids.Unknown {
				err = m.UnknownSectionLoader(load, payloadLen)
			} else {
				_, err = io.CopyN(ioutil.Discard, load, int64(payloadLen))
			}
			return
		}
	} else {
		skipSection = func(id byte, payloadLen uint32) (err error) {
			_, err = io.CopyN(ioutil.Discard, load, int64(payloadLen))
			return
		}
	}

	var seenId byte

	for {
		id, err := load.ReadByte()
		if err != nil {
			if err == io.EOF {
				return 0
			}
			panic(err)
		}

		if id != sectionids.Unknown {
			if id <= seenId {
				panic(fmt.Errorf("section 0x%x follows section 0x%x", id, seenId))
			}
			seenId = id
		}

		if id >= untilSection {
			load.UnreadByte()
			return id
		}

		payloadLen := load.Varuint32()

		if f := sectionLoaders[id]; f != nil {
			f(m, load)
		} else if err := skipSection(id, payloadLen); err != nil {
			panic(err)
		}
	}
}
Example #8
0
func readInitExpr(load loader.L, m *Module) (valueBits uint64, t types.T) {
	op := opcode(load.Byte())

	switch op {
	case opcodeI32Const:
		valueBits = uint64(int64(load.Varint32()))
		t = types.I32

	case opcodeI64Const:
		valueBits = uint64(load.Varint64())
		t = types.I64

	case opcodeF32Const:
		valueBits = uint64(load.Uint32())
		t = types.F32

	case opcodeF64Const:
		valueBits = load.Uint64()
		t = types.F64

	case opcodeGetGlobal:
		i := load.Varuint32()
		if i >= uint32(m.numImportGlobals) {
			panic(fmt.Errorf("import global index out of bounds in initializer expression: %d", i))
		}
		g := m.globals[i]
		valueBits = g.init
		t = g.t

	default:
		panic(fmt.Errorf("unsupported operation in initializer expression: %s", op))
	}

	if op := opcode(load.Byte()); op != opcodeEnd {
		panic(fmt.Errorf("unexpected operation in initializer expression when expecting end: %s", op))
	}

	return
}