You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When using -querylog-format json and querylog enabled, it is possible for invalid json (from the perspective of Golang's encoding/json library) to be written to the querylog when certain characters the json spec doesn't support exist in the bindvars of a query
The bindvar "value" of the query (a []byte) are logged verbatim to the querylog without encoding, which is the main cause of this problem. Golang's json.Marshal(...) avoids these risks by automatically encoding []byte as a base64-encoded string, however the querylog feature is using fmt.Fprintf(...) to marshal json, which of course bypasses this feature
Here are some ideas I can see to fix the problem. All are variants of the same approach really:
Use json.Marshal(...) by default to marshal the json log entry
This will cause the value []byte from bindvars to be base64-encoded
Drawback: Go's encoding/json will handle the base64 transparently, other languages may not 👎
Add a command-line flag to use json.Marshal(...) instead (backwards compatible)
Add a new querylog format (json2 or json-golang for example) to toggle json.Marshal(...)(backwards compatible)
Although it's not backwards-compatible, I'm in favour of option 1 because continuing to log bindvar values without encoding opens users up to bugs
This means you can't unmarshal bindvars back into map[string]*querypb.BindVariable because you get this error:
json: cannot unmarshal string into Go struct field BindVariable.BindVars.type of type query.Type
Instead you're stuck unmarshaling to map[string]interface{} and manually parsing the interface{} -> *querypb.BindVariable. This is another place where using json.Marshal(...) for marshalling would help, although this changes type to a less-human-friendly int32 in logs. A custom (un)marshaler could handle the string<=>int32(*querypb.Type) conversion, however
Overview of the Issue
When using
-querylog-format json
and querylog enabled, it is possible for invalid json (from the perspective of Golang'sencoding/json
library) to be written to the querylog when certain characters the json spec doesn't support exist in the bindvars of a queryThe bindvar "value" of the query (a
[]byte
) are logged verbatim to the querylog without encoding, which is the main cause of this problem. Golang'sjson.Marshal(...)
avoids these risks by automatically encoding[]byte
as a base64-encoded string, however the querylog feature is usingfmt.Fprintf(...)
to marshal json, which of course bypasses this featureHere are some ideas I can see to fix the problem. All are variants of the same approach really:
json.Marshal(...)
by default to marshal the json log entry[]byte
from bindvars to be base64-encodedencoding/json
will handle the base64 transparently, other languages may not 👎json.Marshal(...)
instead (backwards compatible)json2
orjson-golang
for example) to togglejson.Marshal(...)
(backwards compatible)Although it's not backwards-compatible, I'm in favour of option 1 because continuing to log bindvar values without encoding opens users up to bugs
Reproduction Steps
Here is a Go Playground to reproduce the issue
Full repro steps:
-querylog-format json
-querylog-filter-tag 'VTQUERYLOG=1'
-log_queries_to_file <file>
select * from something where id = '\x'
VTQUERYLOG=1
querylog filter in queryjson.Unmarshal(...)
(Go'sencoding/json
)invalid character 'x' in string escape code
\x
being considered a unicode character (or something like that) byjson.Unmarshal
Binary Version
Operating System and Environment details
Log Fragments
No response
The text was updated successfully, but these errors were encountered: