Skip to content

Commit fb97d89

Browse files
committed
Allow setting defaults for SnakeYAML limits
This adds class-level accessors for the following SnakeYAML- specific parser settings: * max_aliases_for_collections * allow_duplicate_keys * allow_recursive_keys * code_point_limit The initial values are based on SnakeYAML Engine's defaults. This PR does not modify those default values. Using these accessors, it should be possible for users to globally change them for all future Psych parser instances without resorting to monkey patches as described in ruby#613 (comment).
1 parent 587c50f commit fb97d89

File tree

1 file changed

+79
-1
lines changed

1 file changed

+79
-1
lines changed

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
}

0 commit comments

Comments
 (0)