Skip to content

Commit d7e4783

Browse files
committed
Fix an infinite recursion issue when registering a Symbol type with a nil packer
That would cause `has_symbol_ext_type = true` to be set, so `msgpack_packer_write_symbol_value` would invoke `Symbol#to_msgpack` which itself would call back to `write_symbol` causing infinite recursion.
1 parent ca6d240 commit d7e4783

6 files changed

Lines changed: 23 additions & 6 deletions

File tree

ChangeLog

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
* Fix an infinite recursion issue when registering a Symbol type with a `nil` packer.
2+
13
2023-03-29 1.7.0:
24

35
* Fix a possible double-free issue when GC triggers inside `_msgpack_rmem_alloc2`.

ext/java/org/msgpack/jruby/ExtensionRegistry.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,11 +141,11 @@ public boolean isRecursive() {
141141
}
142142

143143
public boolean hasPacker() {
144-
return packerProc != null;
144+
return packerProc != null && !packerProc.isNil();
145145
}
146146

147147
public boolean hasUnpacker() {
148-
return unpackerProc != null;
148+
return unpackerProc != null && !unpackerProc.isNil();
149149
}
150150

151151
public IRubyObject getPackerProc() {

ext/java/org/msgpack/jruby/Factory.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,13 @@ public IRubyObject registerType(ThreadContext ctx, IRubyObject[] args) {
102102
if (args[args.length - 1] instanceof RubyHash) {
103103
options = (RubyHash) args[args.length - 1];
104104
packerArg = options.fastARef(runtime.newSymbol("packer"));
105+
if (packerArg != null && packerArg.isNil()) {
106+
packerArg = null;
107+
}
105108
unpackerArg = options.fastARef(runtime.newSymbol("unpacker"));
109+
if (unpackerArg != null && unpackerArg.isNil()) {
110+
unpackerArg = null;
111+
}
106112
IRubyObject optimizedSymbolsParsingArg = options.fastARef(runtime.newSymbol("optimized_symbols_parsing"));
107113
if (optimizedSymbolsParsingArg != null && optimizedSymbolsParsingArg.isTrue()) {
108114
throw runtime.newArgumentError("JRuby implementation does not support the optimized_symbols_parsing option");
@@ -149,7 +155,7 @@ public IRubyObject registerType(ThreadContext ctx, IRubyObject[] args) {
149155

150156
extensionRegistry.put(extModule, (int) typeId, recursive, packerProc, packerArg, unpackerProc, unpackerArg);
151157

152-
if (extModule == runtime.getSymbol()) {
158+
if (extModule == runtime.getSymbol() && !packerProc.isNil()) {
153159
hasSymbolExtType = true;
154160
}
155161

ext/java/org/msgpack/jruby/Packer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ public IRubyObject registerType(ThreadContext ctx, IRubyObject[] args, final Blo
129129

130130
registry.put(extModule, (int) typeId, false, proc, arg, null, null);
131131

132-
if (extModule == runtime.getSymbol()) {
132+
if (extModule == runtime.getSymbol() && !proc.isNil()) {
133133
encoder.hasSymbolExtType = true;
134134
}
135135

ext/msgpack/factory_class.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -222,11 +222,12 @@ static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
222222
unpacker_arg = ID2SYM(rb_intern("from_msgpack_ext"));
223223
break;
224224
case 3:
225-
/* register_type(0x7f, Time, packer: proc-like, unapcker: proc-like) */
225+
/* register_type(0x7f, Time, packer: proc-like, unpacker: proc-like) */
226226
options = argv[2];
227227
if(rb_type(options) != T_HASH) {
228228
rb_raise(rb_eArgError, "expected Hash but found %s.", rb_obj_classname(options));
229229
}
230+
230231
packer_arg = rb_hash_aref(options, ID2SYM(rb_intern("packer")));
231232
unpacker_arg = rb_hash_aref(options, ID2SYM(rb_intern("unpacker")));
232233
break;
@@ -266,7 +267,9 @@ static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
266267
}
267268

268269
if(ext_module == rb_cSymbol) {
269-
fc->has_symbol_ext_type = true;
270+
if(NIL_P(options) || RTEST(rb_hash_aref(options, ID2SYM(rb_intern("packer"))))) {
271+
fc->has_symbol_ext_type = true;
272+
}
270273
if(RTEST(options) && RTEST(rb_hash_aref(options, ID2SYM(rb_intern("optimized_symbols_parsing"))))) {
271274
fc->optimized_symbol_ext_type = true;
272275
}

spec/factory_spec.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,12 @@ class MyType2 < MyType
249249
my.b.should == 2
250250
end
251251

252+
it 'handles Symbol type with `packer: nil`' do
253+
factory = MessagePack::Factory.new
254+
factory.register_type(0x00, Symbol, packer: nil)
255+
expect(factory.load(factory.dump(:foo))).to be == "foo"
256+
end
257+
252258
describe "registering multiple ext type for the same class" do
253259
let(:payload) do
254260
factory = MessagePack::Factory.new

0 commit comments

Comments
 (0)