Fix ReferenceError in QuickJS dispatch for unknown commands#5941
Fix ReferenceError in QuickJS dispatch for unknown commands#5941nickva merged 3 commits intoapache:mainfrom
Conversation
If an unrecognized command is processed by globalThis.dispatch, the error handler attempts to reference cmdkey without it being defined. This throws a ReferenceError instead of generating the intended CouchDB fatal error array. This commit assigns cmd.shift() to a const variable cmdkey before evaluating the switch statement.
|
Thank you for your effort but please complete our standard pull request template. |
|
in addition, the correct fix is |
|
Hi @janl, thanks for taking a look! I considered just replacing cmdkey with cmd in the default case instead of declaring the variable, but there is a catch: because cmd is an array created from JSON.parse(line), evaluating switch(cmd.shift()) removes the command name string from the array. If we use cmd in the error string later, it will print whatever arguments remain in the array rather than the command name itself. For example, if an unknown command payload of ["unknown_cmd", "arg1"] is sent, cmd.shift() leaves cmd as ["arg1"], meaning the error would incorrectly print out unknown command 'arg1'. I also noticed that the SpiderMonkey dispatcher in share/server/loop.js Let me know if that makes sense or if you prefer a different approach! |
|
Thank you for your contribution @Karthikeya1500 that looks like a bug in the command error handling, indeed! Let's add a test for this behavior to ensure we get some coverage. Since eunit tests are a bit tricky to figure out, see if this snippet would work: diff --git i/src/couch/test/eunit/couch_js_tests.erl w/src/couch/test/eunit/couch_js_tests.erl
index 29b303ffb..ecc37d25c 100644
--- i/src/couch/test/eunit/couch_js_tests.erl
+++ w/src/couch/test/eunit/couch_js_tests.erl
@@ -38,7 +38,8 @@ couch_js_test_() ->
?TDEF(should_allow_js_string_mutations),
?TDEF(should_bump_timing_and_call_stats),
?TDEF(should_exit_on_internal_error, 60),
- ?TDEF(should_use_bigint)
+ ?TDEF(should_use_bigint),
+ ?TDEF(should_handle_invalid_command)
])
}
}.
@@ -465,6 +466,11 @@ should_use_bigint(_) ->
?assertThrow({compilation_error, _}, prompt(Proc, [<<"add_fun">>, Src]))
end.
+should_handle_invalid_command(_) ->
+ Proc = couch_query_servers:get_os_process(<<"javascript">>),
+ BadCmd = [<<"bad">>, <<"foo">>],
+ ?assertThrow({unknown_command,<<"unknown command 'bad'">>}, prompt(Proc, BadCmd)).
+
sample_time(Stat) ->
couch_stats:sample([couchdb, query_server, time, Stat]).Just curious, how did you find it? Are you building a custom indexing layer? |
|
"Thanks so much for providing that snippet, @nickva! I've added your test to couch_js_tests.erl As for how I found it: I was actually just exploring the codebase to understand how the QuickJS dispatcher is implemented compared to the SpiderMonkey engine ( loop.js |
nickva
left a comment
There was a problem hiding this comment.
+1
@Karthikeya1500, thank you for your contribution!
That's very cool. It's how often find bugs, just looking around the code or when debugging something unrelated |
Overview
This PR fixes a
ReferenceErrorin the QuickJS query server dispatcher (dispatch-quickjs.js).Previously,
globalThis.dispatchexecutedswitch (cmd.shift())directly. If an unrecognized command was processed and triggered thedefaultfallback block, the code attempted to format an error message referencingcmdkey, which was never defined. This caused the query server to crash and emit a JavaScriptReferenceErrorinstead of gracefully returning the intended["fatal", "unknown_command", ...]error array.This fix correctly captures
const cmdkey = cmd.shift();before evaluating theswitchstatement. This ensures that the command name is preserved and unrecognized commands log the correct command name instead of crashing.Testing recommendations
To test this change, you can manually send an invalid or unrecognized command payload to the QuickJS query server process (e.g.
["unknown_cmd"]).The server should now return a properly formatted CouchDB error array logging the command
["fatal", "unknown_command", "unknown command 'unknown_cmd'"]and gracefully exit, rather than throwing aReferenceErrorexception.Related Issues or Pull Requests
N/A
Checklist
rel/overlay/etc/default.inisrc/docsfolder