Skip to content
Browse files

MB-7764 Don't crash if reduce function calls emit()

If a reduce function called emit(), a danling pointer
was being derreferenced, which lead to a crash.

Change-Id: I3d63ae86e3a4c1027637235210fbd6dc101dc7ac
Reviewed-on: http://review.couchbase.org/24648
Reviewed-by: Volker Mische <volker.mische@gmail.com>
Tested-by: Filipe David Borba Manana <fdmanana@gmail.com>
  • Loading branch information...
1 parent 8f3334b commit c3c0cfb9fec7e8125a5d5895fd3d5d683e3b3f78 @fdmanana fdmanana committed with fdmanana Feb 17, 2013
Showing with 39 additions and 1 deletion.
  1. +5 −0 src/mapreduce/mapreduce.cc
  2. +34 −1 src/mapreduce/test/02-reduce.t
View
5 src/mapreduce/mapreduce.cc
@@ -414,6 +414,10 @@ Handle<Value> emit(const Arguments& args)
{
isolate_data_t *isoData = getIsolateData();
+ if (isoData->ctx->kvs == NULL) {
+ return Undefined();
+ }
+
try {
ErlNifBinary keyJson = jsonStringify(args[0]);
ErlNifBinary valueJson = jsonStringify(args[1]);
@@ -550,6 +554,7 @@ void taskStarted(map_reduce_ctx_t *ctx)
{
ctx->taskId = V8::GetCurrentThreadId();
ctx->taskStartTime = static_cast<long>((clock() / CLOCKS_PER_SEC) * 1000);
+ ctx->kvs = NULL;
}
View
35 src/mapreduce/test/02-reduce.t
@@ -21,7 +21,7 @@
main(_) ->
test_util:init_code_path(),
- etap:plan(126),
+ etap:plan(132),
case (catch test()) of
ok ->
etap:end_tests();
@@ -39,6 +39,7 @@ test() ->
test_reduce_single_function_count(),
test_reduce_single_function_sum(),
test_reduce_multiple_functions(),
+ test_reduce_using_emit(),
test_burst(reduce, 1000),
test_burst(reduce, 10000),
test_burst(reduce, 25000),
@@ -224,6 +225,38 @@ test_reduce_multiple_functions() ->
ok.
+test_reduce_using_emit() ->
+ FunBin = <<"function(key, values, rereduce) {",
+ " for (var i = 0; i < 1000; ++i) { emit(key, values); }",
+ " return values.length; }">>,
+ {ok, Ctx} = mapreduce:start_reduce_context([FunBin]),
+ Results1 = mapreduce:reduce(Ctx, [
+ {<<"\"a\"">>, <<"1">>},
+ {<<"\"b\"">>, <<"2">>},
+ {<<"\"c\"">>, <<"3">>},
+ {<<"\"d\"">>, <<"4">>}
+ ]),
+ Results2 = mapreduce:reduce(Ctx, [
+ {<<"\"x\"">>, <<"666">>}
+ ]),
+ Results3 = mapreduce:reduce(Ctx, [
+ {<<"\"y\"">>, <<"999">>},
+ {<<"\"z\"">>, <<"1000">>}
+ ]),
+ etap:is(Results1, {ok, [<<"4">>]}, "Reduce value is 4"),
+ etap:is(Results2, {ok, [<<"1">>]}, "Reduce value is 1"),
+ etap:is(Results3, {ok, [<<"2">>]}, "Reduce value is 2"),
+ {ok, [Red1]} = Results1,
+ {ok, [Red2]} = Results2,
+ {ok, [Red3]} = Results3,
+ RereduceResult1 = mapreduce:rereduce(Ctx, 1, [Red1, Red2, Red3]),
+ etap:is(RereduceResult1, {ok, <<"3">>}, "Rereduce result is 3"),
+ RereduceResult2 = mapreduce:rereduce(Ctx, 1, [Red1, Red2]),
+ etap:is(RereduceResult2, {ok, <<"2">>}, "Rereduce result is 2"),
+ RereduceResult3 = mapreduce:rereduce(Ctx, 1, [Red1]),
+ etap:is(RereduceResult3, {ok, <<"1">>}, "Rereduce result is 1").
+
+
test_burst(Fun, N) ->
Results = do_burst(Fun, N),
ExpectedResults = [

0 comments on commit c3c0cfb

Please sign in to comment.
Something went wrong with that request. Please try again.