diff --git a/build_deps.sh b/build_deps.sh index 52827f2..17772c6 100755 --- a/build_deps.sh +++ b/build_deps.sh @@ -4,16 +4,21 @@ set -eo pipefail cd -P -- "$(dirname -- "$0")" # download SQLite -url="https://www.sqlite.org/2022/sqlite-amalgamation-3400100.zip" - -curl "$url" > sqlite3/sqlite.zip -unzip -d sqlite3/ sqlite3/sqlite.zip -mv sqlite3/sqlite-amalgamation-*/sqlite3* sqlite3/ -rm -rf sqlite3/sqlite-amalgamation-* -rm sqlite3/sqlite.zip +if [ ! -f "sqlite3/sqlite3.c" ]; then + url="https://www.sqlite.org/2022/sqlite-amalgamation-3400100.zip" + curl "$url" > sqlite3/sqlite.zip + unzip -d sqlite3/ sqlite3/sqlite.zip + mv sqlite3/sqlite-amalgamation-*/sqlite3* sqlite3/ + rm -rf sqlite3/sqlite-amalgamation-* + rm sqlite3/sqlite.zip +fi # build SQLite -zig cc --target=wasm32-wasi -flto -g0 -O2 -o embed/sqlite3.wasm sqlite3/*.c \ +zig cc --target=wasm32-wasi -flto -g0 -O2 \ + -o embed/sqlite3.wasm sqlite3/*.c \ + -mmutable-globals \ + -mbulk-memory -mreference-types \ + -mnontrapping-fptoint -msign-ext \ -DSQLITE_OS_OTHER=1 -DSQLITE_BYTEORDER=1234 \ -DHAVE_ISNAN -DHAVE_MALLOC_USABLE_SIZE \ -DSQLITE_DQS=0 \ @@ -26,6 +31,7 @@ zig cc --target=wasm32-wasi -flto -g0 -O2 -o embed/sqlite3.wasm sqlite3/*.c \ -DSQLITE_OMIT_PROGRESS_CALLBACK \ -DSQLITE_OMIT_SHARED_CACHE \ -DSQLITE_OMIT_AUTOINIT \ + -DSQLITE_OMIT_UTF16 \ -Wl,--export=sqlite3_open_v2 \ -Wl,--export=sqlite3_close \ -Wl,--export=sqlite3_prepare_v2 \ diff --git a/sqlite3.go b/conn.go similarity index 83% rename from sqlite3.go rename to conn.go index c00aed9..0242b01 100644 --- a/sqlite3.go +++ b/conn.go @@ -89,7 +89,7 @@ func Open(name string, flags uint64, vfs string) (*Conn, error) { namePtr := c.newString(name) defer c.free(namePtr) - handlePtr := c.newPtr() + handlePtr := c.newBytes(4) defer c.free(handlePtr) var vfsPtr uint32 @@ -119,7 +119,7 @@ func (c *Conn) Errmsg() error { if err != nil { return err } - return errors.New(c.getString(r[0])) + return errors.New(c.getString(uint32(r[0]), 64)) } func (c *Conn) Close() error { @@ -141,37 +141,43 @@ func (c *Conn) free(ptr uint32) { } } -func (c *Conn) newPtr() uint32 { - r, err := c.api.malloc.Call(context.TODO(), 4) +func (c *Conn) newBytes(len uint32) uint32 { + r, err := c.api.malloc.Call(context.TODO(), uint64(len)) if err != nil { panic(err) } + if r[0] == 0 { + panic("sqlite3: out of memory") + } return uint32(r[0]) } func (c *Conn) newString(str string) uint32 { - r, err := c.api.malloc.Call(context.TODO(), uint64(len(str)+1)) - if err != nil { - panic(err) + ptr := c.newBytes(uint32(len(str) + 1)) + + buf, ok := c.memory.Read(ptr, uint32(len(str)+1)) + if !ok { + c.api.free.Call(context.TODO(), uint64(ptr)) + panic("sqlite3: failed to init string") } - ptr := uint32(r[0]) - if ok := c.memory.Write(ptr, []byte(str)); !ok { - panic("failed init string") - } - if ok := c.memory.WriteByte(ptr+uint32(len(str)), 0); !ok { - panic("failed init string") - } + buf[len(str)] = 0 + copy(buf, str) return ptr } -func (c *Conn) getString(ptr uint64) string { - buf, ok := c.memory.Read(uint32(ptr), 64) +func (c *Conn) getString(ptr, maxlen uint32) string { + buf, ok := c.memory.Read(ptr, maxlen) if !ok { - panic("failed read string") + if size := c.memory.Size(); ptr < size { + buf, ok = c.memory.Read(ptr, size-ptr) + } + if !ok { + panic("sqlite3: invalid pointer") + } } if i := bytes.IndexByte(buf, 0); i < 0 { - panic("failed read string") + panic("sqlite3: missing NUL terminator") } else { return string(buf[:i]) } diff --git a/sqlite3/main.c b/sqlite3/main.c index 1406d78..499f532 100644 --- a/sqlite3/main.c +++ b/sqlite3/main.c @@ -1,6 +1,6 @@ #include "sqlite3.h" -int main(int argc, char *argv[]) { +int main() { int rc = sqlite3_initialize(); if (rc != SQLITE_OK) return -1; }