tarantool / tarantool/tarantool
sql: unterminated legacy name when the uppercase form is longer
Nobody has claimed this yet.
- Dominant language
- Lua
- Stars
- 3.7k
- Forks
- 419
- Avg merge
- 1d 23h
- Merged PRs (30d)
- 88
Description
Bug description
sql_legacy_name_new() in src/box/sql/util.c uppercases an unquoted SQL identifier with ucasemap_utf8ToUpper() into a buffer sized for the input. When the uppercased form is longer than the input, the first call returns U_BUFFER_OVERFLOW_ERROR and the code reallocates a larger buffer and retries, but it doesn't reset status to U_ZERO_ERROR first. ICU returns right away when the incoming status already holds a failure, so the retry writes nothing and returns 0. The returned name has no NUL terminator and its tail is uninitialized heap memory, and the callers then use it as a C string (space_by_name0(), strcmp(), ...). The legacy-name lookup fails, and the lookup itself reads past the written bytes.
Any client SQL with an unquoted identifier whose uppercase form is longer in bytes hits this, for example Greek ΐ (U+0390, 2 bytes) whose uppercase is Ϊ́ (U+0399 U+0308 U+0301, 6 bytes). Identifiers whose uppercase is not longer take the early return before the retry, so ASCII names are unaffected.
- OS: MacOS
- OS Version: macOS 26 (Darwin 25.6.0), also present in the sources on Linux
- Architecture: arm64
Tarantool 3.9.0-entrypoint (master, commit 9ca342c5)
Steps to reproduce
Reproducer script:
#!/usr/bin/env tarantool
box.cfg{}
-- U+0390 is 2 bytes, its uppercase form U+0399 U+0308 U+0301 is 6 bytes.
local s = box.schema.space.create('\xCE\x99\xCC\x88\xCC\x81',
{format = {{'a', 'integer'}}})
s:create_index('pk')
s:insert({1})
local res, err = box.execute('SELECT a FROM \xCE\x90 WHERE a = 1;')
print(res ~= nil and require('json').encode(res.rows) or err)
os.exit()
How to run:
Just type tarantool test.lua.
Actual behavior
Space 'ΐ' does not exist
The space is not found through its legacy uppercased name because the retry never wrote the uppercased bytes, and the lookup runs strlen()/strcmp() over a buffer that has no terminator.
Expected behavior
[[1]]
The unquoted identifier resolves to the space named by its uppercased form, the same way it does for ASCII identifiers (SELECT * FROM asd finds ASD).
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in src/box/sql/util.c at sql_legacy_name_new() and inspect the retry after ucasemap_utf8ToUpper() reports U_BUFFER_OVERFLOW_ERROR. Run the provided Lua reproducer with tarantool test.lua; done when the unquoted Greek identifier resolves to the created space and prints [[1]].
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c, lua, sql
- Domain
- database
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 88/100