Skip to content

Commit 48cdab3

Browse files
authored
Merge pull request #647 from headius/jruby_default_limits
Allow setting defaults for SnakeYAML limits
2 parents 587c50f + 0c1754e commit 48cdab3

2 files changed

Lines changed: 98 additions & 1 deletion

File tree

ext/java/org/jruby/ext/psych/PsychParser.java

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import org.jruby.RubyIO;
4242
import org.jruby.RubyKernel;
4343
import org.jruby.RubyModule;
44+
import org.jruby.RubyNumeric;
4445
import org.jruby.RubyObject;
4546
import org.jruby.RubyString;
4647
import org.jruby.anno.JRubyMethod;
@@ -113,6 +114,13 @@ public static void initPsychParser(Ruby runtime, RubyModule psych) {
113114
psychParser.defineConstant("UTF16BE", runtime.newFixnum(YAML_UTF16BE_ENCODING.ordinal()));
114115

115116
psychParser.defineAnnotatedMethods(PsychParser.class);
117+
118+
// defaults for SnakeYAML load settings
119+
LoadSettings defaults = LoadSettings.builder().build();
120+
psychParser.setInternalVariable("max_aliases_for_collections", runtime.newFixnum(defaults.getMaxAliasesForCollections()));
121+
psychParser.setInternalVariable("allow_duplicate_keys", runtime.newBoolean(defaults.getAllowDuplicateKeys()));
122+
psychParser.setInternalVariable("allow_recursive_keys", runtime.newBoolean(defaults.getAllowRecursiveKeys()));
123+
psychParser.setInternalVariable("code_point_limit", runtime.newFixnum(defaults.getCodePointLimit()));
116124
}
117125

118126
public PsychParser(Ruby runtime, RubyClass klass) {
@@ -131,7 +139,15 @@ public PsychParser(Ruby runtime, RubyClass klass) {
131139
this.start_mapping = sites[Call.start_mapping.ordinal()];
132140
this.end_mapping = sites[Call.end_mapping.ordinal()];
133141
this.end_stream = sites[Call.end_stream.ordinal()];
134-
this.loadSettingsBuilder = LoadSettings.builder().setSchema(new CoreSchema());
142+
143+
// prepare settings builder and apply global defaults
144+
LoadSettingsBuilder lsb = LoadSettings.builder();
145+
lsb.setSchema(new CoreSchema());
146+
lsb.setMaxAliasesForCollections(((IRubyObject) klass.getInternalVariable("max_aliases_for_collections")).convertToInteger().getIntValue());
147+
lsb.setAllowDuplicateKeys(((IRubyObject) klass.getInternalVariable("allow_duplicate_keys")).isTrue());
148+
lsb.setAllowRecursiveKeys(((IRubyObject) klass.getInternalVariable("allow_recursive_keys")).isTrue());
149+
lsb.setCodePointLimit(((IRubyObject) klass.getInternalVariable("code_point_limit")).convertToInteger().getIntValue());
150+
this.loadSettingsBuilder = lsb;
135151
}
136152

137153
private IRubyObject stringOrNilForAnchor(ThreadContext context, Optional<Anchor> value) {
@@ -563,6 +579,68 @@ public IRubyObject code_point_limit(ThreadContext context) {
563579
return context.runtime.newFixnum(buildSettings().getCodePointLimit());
564580
}
565581

582+
// class-level accessors for default values
583+
584+
@JRubyMethod(name = "max_aliases_for_collections=", meta = true)
585+
public static IRubyObject max_aliases_for_collections_set(ThreadContext context, IRubyObject self, IRubyObject max) {
586+
int maxAliasesForCollections = RubyNumeric.num2int(max);
587+
588+
if (maxAliasesForCollections <= 0) {
589+
throw context.runtime.newRangeError("max_aliases_for_collections must be positive");
590+
}
591+
592+
self.getInternalVariables().setInternalVariable("max_aliases_for_collections", max);
593+
594+
return max;
595+
}
596+
597+
@JRubyMethod(name = "max_aliases_for_collections")
598+
public static IRubyObject max_aliases_for_collections(ThreadContext context, IRubyObject self) {
599+
return (IRubyObject) self.getInternalVariables().getInternalVariable("max_aliases_for_collections");
600+
}
601+
602+
@JRubyMethod(name = "allow_duplicate_keys=", meta = true)
603+
public static IRubyObject allow_duplicate_keys_set(IRubyObject self, IRubyObject allow) {
604+
self.getInternalVariables().setInternalVariable("allow_duplicate_keys", allow);
605+
606+
return allow;
607+
}
608+
609+
@JRubyMethod(name = "allow_duplicate_keys", meta = true)
610+
public static IRubyObject allow_duplicate_keys(ThreadContext context, IRubyObject self) {
611+
return (IRubyObject) self.getInternalVariables().getInternalVariable("allow_duplicate_keys");
612+
}
613+
614+
@JRubyMethod(name = "allow_recursive_keys=", meta = true)
615+
public static IRubyObject allow_recursive_keys_set(IRubyObject self, IRubyObject allow) {
616+
self.getInternalVariables().setInternalVariable("allow_recursive_keys", allow);
617+
618+
return allow;
619+
}
620+
621+
@JRubyMethod(name = "allow_recursive_keys", meta = true)
622+
public static IRubyObject allow_recursive_keys(ThreadContext context, IRubyObject self) {
623+
return (IRubyObject) self.getInternalVariables().getInternalVariable("allow_recursive_keys");
624+
}
625+
626+
@JRubyMethod(name = "code_point_limit=", meta = true)
627+
public static IRubyObject code_point_limit_set(ThreadContext context, IRubyObject self, IRubyObject limit) {
628+
int codePointLimit = RubyNumeric.num2int(limit);
629+
630+
if (codePointLimit <= 0) {
631+
throw context.runtime.newRangeError("code_point_limit must be positive");
632+
}
633+
634+
self.getInternalVariables().setInternalVariable("code_point_limit", limit);
635+
636+
return limit;
637+
}
638+
639+
@JRubyMethod(name = "code_point_limit", meta = true)
640+
public static IRubyObject code_point_limit(ThreadContext context, IRubyObject self) {
641+
return (IRubyObject) self.getInternalVariables().getInternalVariable("code_point_limit");
642+
}
643+
566644
private LoadSettings buildSettings() {
567645
return loadSettingsBuilder.build();
568646
}

test/psych/test_parser.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,25 @@ def test_event_location
384384
[:end_stream, [2, 0, 2, 0]]], events
385385
end
386386

387+
if Psych::Parser.method_defined?(:code_point_limit)
388+
def test_code_point_limit
389+
yaml = "foo: bar\n" * 500_000
390+
assert_raise(org.snakeyaml.engine.v2.exceptions.YamlEngineException) do
391+
Psych.load(yaml)
392+
end
393+
394+
assert_nothing_raised do
395+
begin
396+
old_code_point_limit, Psych::Parser.code_point_limit = Psych::Parser::code_point_limit, 5_000_000
397+
398+
Psych.load(yaml)
399+
ensure
400+
Psych::Parser.code_point_limit = old_code_point_limit
401+
end
402+
end
403+
end
404+
end
405+
387406
def assert_called call, with = nil, parser = @parser
388407
if with
389408
call = parser.handler.calls.find { |x|

0 commit comments

Comments
 (0)