Skip to content
This repository has been archived by the owner on Nov 16, 2022. It is now read-only.

Commit

Permalink
Merge pull request #1936 from bandprotocol/handle-span-exceed
Browse files Browse the repository at this point in the history
go-owasm: Return error if writing beyond the provided span length
  • Loading branch information
taobun committed Jun 15, 2020
2 parents 997c126 + 7af9629 commit ae34419
Show file tree
Hide file tree
Showing 14 changed files with 114 additions and 46 deletions.
1 change: 1 addition & 0 deletions CHANGELOG_UNRELEASED.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

### Owasm

- (impv) [\#1936](https://github.com/bandprotocol/bandchain/pull/1936) Return error if writing beyond the span capacity.
- (impv) [#\1941](https://github.com/bandprotocol/bandchain/pull/1941) Fix how to build share object in Linux.
- (feat) [\#1922](https://github.com/bandprotocol/bandchain/pull/1922) Add wat to wasm function.

Expand Down
1 change: 1 addition & 0 deletions go-owasm/api/bindings.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ enum Error {
ResolveNamesError = 5,
ValidateError = 6,
UnknownError = 7,
SpanExceededCapacityError = 8,
};
typedef int32_t Error;

Expand Down
27 changes: 15 additions & 12 deletions go-owasm/api/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ import (
)

var (
ErrCompliationError = errors.New("compile fail")
ErrRunError = errors.New("run fail")
ErrParseError = errors.New("parse fail")
ErrWriteBinaryError = errors.New("write binary fail")
ErrResolvesNamesFail = errors.New("resolve names fail")
ErrValidateError = errors.New("validate fail")
ErrUnknownError = errors.New("unknown error")
ErrCompliationFail = errors.New("compile fail")
ErrRunFail = errors.New("run fail")
ErrParseFail = errors.New("parse fail")
ErrWriteBinaryFail = errors.New("write binary fail")
ErrResolvesNamesFail = errors.New("resolve names fail")
ErrValidateFail = errors.New("validate fail")
ErrUnknownError = errors.New("unknown error")
ErrSpanExceededCapacity = errors.New("span exceeded capacity")
)

// parseError - returns parsed error from errors code on bindings.h
Expand All @@ -20,19 +21,21 @@ func parseError(code int32) error {
case 0:
return nil
case 1:
return ErrCompliationError
return ErrCompliationFail
case 2:
return ErrRunError
return ErrRunFail
case 3:
return ErrParseError
return ErrParseFail
case 4:
return ErrWriteBinaryError
return ErrWriteBinaryFail
case 5:
return ErrResolvesNamesFail
case 6:
return ErrValidateError
return ErrValidateFail
case 7:
return ErrUnknownError
case 8:
return ErrSpanExceededCapacity
default:
return ErrUnknownError
}
Expand Down
8 changes: 4 additions & 4 deletions go-owasm/api/lib.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ import (
"unsafe"
)

func Compile(code []byte) ([]byte, error) {
func Compile(code []byte, spanSize int) ([]byte, error) {
inputSpan := copySpan(code)
defer freeSpan(inputSpan)
outputSpan := newSpan(SpanSize)
outputSpan := newSpan(spanSize)
defer freeSpan(outputSpan)
err := parseError(int32(C.do_compile(inputSpan, &outputSpan)))
return readSpan(outputSpan), err
Expand Down Expand Up @@ -61,10 +61,10 @@ func run(code []byte, isPrepare bool, env EnvInterface) error {
})))
}

func Wat2Wasm(code []byte) ([]byte, error) {
func Wat2Wasm(code []byte, spanSize int) ([]byte, error) {
inputSpan := copySpan(code)
defer freeSpan(inputSpan)
outputSpan := newSpan(SpanSize)
outputSpan := newSpan(spanSize)
defer freeSpan(outputSpan)
err := parseError(int32(C.do_wat2wasm(inputSpan, &outputSpan)))
return readSpan(outputSpan), err
Expand Down
21 changes: 16 additions & 5 deletions go-owasm/api/lib_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ import (
"github.com/stretchr/testify/require"
)

const (
SpanSize = 1 * 1024 * 1024
)

func readWatFile(fileName string) []byte {
code, err := ioutil.ReadFile(fmt.Sprintf("./../wasm/%s.wat", fileName))
if err != nil {
Expand All @@ -26,7 +30,7 @@ func readWasmFile(fileName string) []byte {

func TestSuccessWatToOwasm(t *testing.T) {
code := readWatFile("test")
wasm, err := Wat2Wasm(code)
wasm, err := Wat2Wasm(code, SpanSize)
require.NoError(t, err)

expectedWasm := readWasmFile("test")
Expand All @@ -35,12 +39,19 @@ func TestSuccessWatToOwasm(t *testing.T) {

func TestFailEmptyWatContent(t *testing.T) {
code := []byte("")
_, err := Wat2Wasm(code)
require.Equal(t, ErrParseError, err)
_, err := Wat2Wasm(code, SpanSize)
require.Equal(t, ErrParseFail, err)
}

func TestFailInvalidWatContent(t *testing.T) {
code := []byte("invalid wat content")
_, err := Wat2Wasm(code)
require.Equal(t, ErrParseError, err)
_, err := Wat2Wasm(code, SpanSize)
require.Equal(t, ErrParseFail, err)
}

func TestFailSpanExceededCapacity(t *testing.T) {
code := readWatFile("test")
smallSpanSize := 10
_, err := Wat2Wasm(code, smallSpanSize)
require.EqualError(t, err, "span exceeded capacity")
}
Binary file modified go-owasm/api/libgo_owasm.dylib
Binary file not shown.
Binary file modified go-owasm/api/libgo_owasm.so
Binary file not shown.
4 changes: 0 additions & 4 deletions go-owasm/api/span.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,6 @@ package api
import "C"
import "unsafe"

const (
SpanSize = 1 * 1024 * 1024
)

func newSpan(size int) C.Span {
return C.Span{
ptr: (*C.uint8_t)(C.malloc(C.uintptr_t(size))),
Expand Down
2 changes: 2 additions & 0 deletions go-owasm/go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
module github.com/bandprotocol/bandchain/go-owasm

go 1.13

require github.com/stretchr/testify v1.6.1
10 changes: 10 additions & 0 deletions go-owasm/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
7 changes: 4 additions & 3 deletions go-owasm/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ func (e *Env) GetExternalData(eid int64, vid int64) []byte {
return []byte("switez")
}

func Wat2Wasm(fileName string) error {
func Wat2Wasm(fileName string, spanSize int) error {
code, _ := ioutil.ReadFile(fmt.Sprintf("./wasm/%s.wat", fileName))
wasm, err := api.Wat2Wasm(code)
wasm, err := api.Wat2Wasm(code, spanSize)
if err != nil {
panic(err)
}
Expand All @@ -65,7 +65,8 @@ func Wat2Wasm(fileName string) error {
func main() {
fmt.Println("Hello, World!")
code, _ := ioutil.ReadFile("./wasm/fun3.wat")
wasm, e := api.Wat2Wasm(code)
spanSize := 1 * 1024 * 1024
wasm, e := api.Wat2Wasm(code, spanSize)
fmt.Println("wasm", wasm)
fmt.Println(e)
}
4 changes: 3 additions & 1 deletion go-owasm/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#[repr(i32)]
#[derive(Debug, PartialEq)]
pub enum Error {
NoError = 0,
CompliationError = 1,
Expand All @@ -7,5 +8,6 @@ pub enum Error {
WriteBinaryError = 4,
ResolveNamesError = 5,
ValidateError = 6,
UnknownError = 7
UnknownError = 7,
SpanExceededCapacityError = 8
}
10 changes: 2 additions & 8 deletions go-owasm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,7 @@ use wabt::wat2wasm;
pub extern "C" fn do_compile(input: Span, output: &mut Span) -> Error {
// TODO: Define error when compile code.
match compile(input.read()) {
Ok(out) => {
output.write(&out);
Error::NoError
}
Ok(out) => output.write(&out),
Err(_) => Error::CompliationError,
}
}
Expand All @@ -38,10 +35,7 @@ pub extern "C" fn do_run(code: Span, is_prepare: bool, env: Env) -> Error {
#[no_mangle]
pub extern "C" fn do_wat2wasm(input: Span, output: &mut Span) -> Error {
match wat2wasm(input.read()) {
Ok(_wasm) => {
output.write(&_wasm);
Error::NoError
},
Ok(_wasm) => output.write(&_wasm),
Err(e) => {
match e.kind() {
wabt::ErrorKind::Parse(_) => Error::ParseError,
Expand Down
65 changes: 56 additions & 9 deletions go-owasm/src/span.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use crate::error::Error;

#[derive(Copy, Clone)]
#[repr(C)]
pub struct Span {
Expand All @@ -7,30 +9,75 @@ pub struct Span {
}

impl Span {
// TODO
// Create span.
pub fn create(data: &[u8]) -> Span {
Span {
ptr: data.as_ptr() as *mut u8,
len: data.len(),
cap: data.len(),
}
}

/// TODO
/// Read data from the span.
pub fn read(&self) -> &[u8] {
unsafe { std::slice::from_raw_parts(self.ptr, self.len) }
}

/// TODO
pub fn write(&mut self, data: &[u8]) {
// TODO: Do not allow write if data.len() exceeds cap.
/// Write data to the span.
pub fn write(&mut self, data: &[u8]) -> Error {
if self.len + data.len() > self.cap {
return Error::SpanExceededCapacityError
}
unsafe { std::ptr::copy(data.as_ptr(), self.ptr.offset(self.len as isize), data.len()) }
self.len += data.len();
unsafe { std::ptr::copy(data.as_ptr(), self.ptr, data.len()) }
Error::NoError
}
}

#[cfg(test)]
mod test {
// use super::*;
// TODO
use super::*;

#[test]
fn test_create_and_read_span_ok() {
let data: Vec<u8> = vec![1, 2, 3, 4, 5];
let span = Span::create(data.as_slice());
let span_data = &span.read();
let span_data_vec = span_data.to_vec();
assert_eq!(span_data_vec.len(), data.len());
assert_eq!(span_data_vec[0], data[0]);
assert_eq!(span_data_vec[1], data[1]);
assert_eq!(span_data_vec[2], data[2]);
assert_eq!(span_data_vec[3], data[3]);
assert_eq!(span_data_vec[4], data[4]);
}

#[test]
fn test_write_span_ok() {
let mut empty_space = vec![0u8; 32];
let mut span = Span{ ptr: empty_space.as_mut_ptr(), len: 0, cap: 32 };

let data: Vec<u8> = vec![1, 2, 3, 4, 5];
assert_eq!(span.write(data.as_slice()), Error::NoError);
assert_eq!(span.len, 5);
assert_eq!(span.cap, 32);
assert_eq!(empty_space[0], 1);
assert_eq!(empty_space[5], 0);

assert_eq!(span.write(data.as_slice()), Error::NoError);
assert_eq!(span.len, 10);
assert_eq!(span.cap, 32);
assert_eq!(empty_space[0], 1);
assert_eq!(empty_space[5], 1);
assert_eq!(empty_space[9], 5);
}

#[test]
fn test_write_span_fail() {
let mut empty_space = vec![0u8; 3];
let mut span = Span{ ptr: empty_space.as_mut_ptr(), len: 0, cap: 3 };
let data: Vec<u8> = vec![1, 2, 3, 4, 5];
span.write(data.as_slice());
assert_eq!(span.write(data.as_slice()), Error::SpanExceededCapacityError);
}
}

0 comments on commit ae34419

Please sign in to comment.