mirror of
https://github.com/AgentSeal/codeburn.git
synced 2026-05-18 06:04:36 +00:00
Fix node:sqlite V8 crash on invalid UTF-8 in text columns (#272)
node:sqlite calls v8::String::NewFromUtf8 with kAbort on TEXT columns. Cursor chat blobs often contain truncated multi-byte chars from streaming boundaries, which triggers a V8 CHECK abort (not a JS exception). Select all text-content columns as CAST(col AS BLOB) so node:sqlite returns Uint8Array instead. Decode in JS with TextDecoder fatal:false which replaces bad bytes with U+FFFD. Covers all three SQLite providers (Cursor, Goose, OpenCode). Removes the version blocklist (MIN_NODE_22_PATCH) and lowers engines requirement from >=22.20 to >=22 since the BLOB cast approach works on all Node 22.x versions. Closes #264 Closes #250
This commit is contained in:
parent
d142bd97ef
commit
02f4635cec
6 changed files with 101 additions and 76 deletions
39
tests/blob-to-text.test.ts
Normal file
39
tests/blob-to-text.test.ts
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
import { describe, it, expect } from 'vitest'
|
||||
import { blobToText } from '../src/sqlite.js'
|
||||
|
||||
describe('blobToText', () => {
|
||||
it('returns empty string for null', () => {
|
||||
expect(blobToText(null)).toBe('')
|
||||
})
|
||||
|
||||
it('returns empty string for undefined', () => {
|
||||
expect(blobToText(undefined)).toBe('')
|
||||
})
|
||||
|
||||
it('passes through strings unchanged', () => {
|
||||
expect(blobToText('hello world')).toBe('hello world')
|
||||
})
|
||||
|
||||
it('decodes valid UTF-8 Uint8Array', () => {
|
||||
const buf = new TextEncoder().encode('café ☕')
|
||||
expect(blobToText(buf)).toBe('café ☕')
|
||||
})
|
||||
|
||||
it('replaces invalid UTF-8 bytes with U+FFFD instead of crashing', () => {
|
||||
const buf = new Uint8Array([0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x80, 0xfe])
|
||||
const result = blobToText(buf)
|
||||
expect(result).toContain('Hello')
|
||||
expect(result).toContain('<27>')
|
||||
})
|
||||
|
||||
it('handles truncated multi-byte sequence', () => {
|
||||
// é in UTF-8 is [0xc3, 0xa9]. Truncate to just [0xc3].
|
||||
const buf = new Uint8Array([0x63, 0x61, 0x66, 0xc3])
|
||||
const result = blobToText(buf)
|
||||
expect(result).toBe('caf<61>')
|
||||
})
|
||||
|
||||
it('handles empty Uint8Array', () => {
|
||||
expect(blobToText(new Uint8Array(0))).toBe('')
|
||||
})
|
||||
})
|
||||
Loading…
Add table
Add a link
Reference in a new issue