Skip to content

Commit 782c497

Browse files
committed
cgosqlite: add support for compiling with SQLITE_ENABLE_API_ARMOR
The build tag `sqlite_enable_api_armor` causes sqlite to be compiled with `SQLITE_ENABLE_API_ARMOR`. The new function `APIArmorEnabled` reports wether sqlite was compiled with `SQLITE_ENABLE_API_ARMOR`. Updates tailscale/corp#37039 Signed-off-by: Percy Wegmann <percy@tailscale.com>
1 parent 558b1f9 commit 782c497

5 files changed

Lines changed: 97 additions & 0 deletions

File tree

.github/workflows/test-sqlite.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,8 @@ jobs:
2929
- name: Race
3030
run: go test -v -race ./...
3131

32+
- name: Race with sqlite_enable_api_armor
33+
run: go test -v -race -tags sqlite_enable_api_armor
34+
3235
- name: No CGO build
3336
run: CGO_ENABLED=0 go install ./...
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//go:build !sqlite_enable_api_armor
2+
3+
package cgosqlite
4+
5+
import (
6+
"testing"
7+
)
8+
9+
func TestAPIArmorDisabled(t *testing.T) {
10+
testAPIArmor(t, false)
11+
}

cgosqlite/apiarmor_enabled_test.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//go:build sqlite_enable_api_armor
2+
3+
package cgosqlite
4+
5+
import (
6+
"testing"
7+
)
8+
9+
func TestAPIArmorEnabled(t *testing.T) {
10+
testAPIArmor(t, true)
11+
}

cgosqlite/apiarmor_test.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package cgosqlite
2+
3+
import (
4+
"path/filepath"
5+
"sync/atomic"
6+
"testing"
7+
8+
"github.com/tailscale/sqlite/sqliteh"
9+
)
10+
11+
// testAPIArmor provides a common function for testing SQLITE_ENABLE_API_ARMOR.
12+
func testAPIArmor(t *testing.T, wantMisuseError bool) {
13+
if wantMisuseError && !APIArmorEnabled() {
14+
t.Fatal("APIArmor is not enabled")
15+
} else if !wantMisuseError && APIArmorEnabled() {
16+
t.Fatal("APIArmor is enabled")
17+
}
18+
19+
var gotMisuseLog atomic.Bool
20+
err := SetLogCallback(func(code sqliteh.Code, msg string) {
21+
if code == sqliteh.SQLITE_MISUSE {
22+
gotMisuseLog.Store(true)
23+
}
24+
})
25+
if err != nil {
26+
t.Fatal(err)
27+
}
28+
29+
db, err := Open(filepath.Join(t.TempDir(), "test.db"), sqliteh.OpenFlagsDefault, "")
30+
if err != nil {
31+
t.Fatal(err)
32+
}
33+
err = db.Close()
34+
if err != nil {
35+
t.Fatal(err)
36+
}
37+
38+
// Configuring AutoCheckpoint on a closed database should result in a misuse error
39+
// if and only if APIArmorEnabled().
40+
got := db.AutoCheckpoint(1)
41+
if wantMisuseError {
42+
if got == nil || got.Error() != "SQLITE_MISUSE" {
43+
t.Fatalf("want SQLITE_MISUSE, got %s", got)
44+
}
45+
46+
if !gotMisuseLog.Load() {
47+
t.Fatal("did not get SQLITE_MISUSE in LogCallback")
48+
}
49+
} else {
50+
if got != nil && got.Error() == "SQLITE_MISUSE" {
51+
t.Fatalf("want no error, got %s", got)
52+
}
53+
54+
if gotMisuseLog.Load() {
55+
t.Fatal("got SQLITE_MISUSE in LogCallback")
56+
}
57+
}
58+
}

cgosqlite/cgosqlite.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,15 @@ package cgosqlite
4646
// libm is required by the FTS5 extension, on Linux.
4747
#cgo linux LDFLAGS: -lm
4848
49+
// Enable API armor.
50+
#cgo sqlite_enable_api_armor CFLAGS: -DSQLITE_ENABLE_API_ARMOR
51+
52+
#ifdef SQLITE_ENABLE_API_ARMOR
53+
int api_armor_enabled=1;
54+
#else
55+
int api_armor_enabled=0;
56+
#endif
57+
4958
#include "cgosqlite.h"
5059
*/
5160
import "C"
@@ -502,3 +511,8 @@ func stringFromBytes(b []byte) string {
502511
internCache.Store(s, s)
503512
return s
504513
}
514+
515+
// APIArmorEnabled reports whether or not sqlite was compiled with SQLITE_ENABLE_API_ARMOR
516+
func APIArmorEnabled() bool {
517+
return C.api_armor_enabled == 1
518+
}

0 commit comments

Comments
 (0)