-
-
Notifications
You must be signed in to change notification settings - Fork 91
Fix prototype keys causing crash in color parsing and invalid colors in color coercion expressions #1036
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix prototype keys causing crash in color parsing and invalid colors in color coercion expressions #1036
Conversation
parseCssColor checks `namedColors[input]` to see if the given color string is a predetermined named color. If "__proto__" or any other key found in Object.prototype was used, the evaluated value was truthy, and the function attempted to destructure the returned value, which throws an error. This commit fixes that issue by using getOwn() to access only own properties of the namedColors object.
Color coercion (Coercion class) uses EvaluationContext.parseColor to parse color strings. EvaluationContext has an internal cache for color strings, which it checks before parsing to skip parsing the same value multiple times. If a color coercion expression was passed "__proto__" or some other key present in Object.prototype, the parseColor function would skip parsing altogether as this._parseColorCache["__proto__"] evaluated to a truthy value, and thus parseColor thought the value was cached and returned the evaluated value directly. This caused the entire coercion expression to evaluate to the value of Object.prototype, which in the end resulted in the color being [null, null, null, null] somewhere in maplibre-gl-js. Fixed by creating the cache with a null prototype, instead of an empty object literal.
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #1036 +/- ##
=======================================
Coverage 92.74% 92.74%
=======================================
Files 108 108
Lines 4728 4730 +2
Branches 1347 1347
=======================================
+ Hits 4385 4387 +2
Misses 343 343 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
@@ -10,5 +10,17 @@ | |||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noticed that there were both *.output-api-supported.json
and *.output.json
files in the tests, but was unable to find references to output-api-supported
or api-supported
in the codebase, other than a changelog entry saying --mapbox-api-supported
had been removed from gl-style-validation
in 14.0.0. Are the .output-api-supported.json
files still used, or subject for removal in a later PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't find anything related to this in the history of the repo, I'm not sure they were ever used, and also from a very shallow test I made these looks duplicates of the output files, so I would recommend removing them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure. Remove in this PR or shall I make a separate PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A separate PR seems like the right approach.
c526145
to
89d3c87
Compare
From #1025
This PR fixes two issues:
text-color: "red"
),parse_css_color.ts
attempted to look up named colors from an object literal by doingnamedColors[input]
. If the color string was"__proto__"
or"toString"
or some other key in theObject
prototype, the value was truthy, and caused an unhandled error to be thrown because the value was destructured.maplibre-style-spec/src/expression/types/parse_css_color.ts
Lines 40 to 44 in 91175b3
Coercion
expression was used to coerce an expression's string value to a color (e.g.to_color
), it usedEvaluationContext.parseColor()
which checked if the string had already been parsed and cached. The cache lookup was done viathis._parseColorCache[input]
, whereinput
comes from the user controlled style. As a result, the input was never parsed as the value was truthy, and the value from the prototype was returned and became the expression's value.maplibre-style-spec/src/expression/evaluation_context.ts
Line 16 in 91175b3
maplibre-style-spec/src/expression/evaluation_context.ts
Lines 48 to 53 in 91175b3
Fixing issue 1 revealed issue 2, as
EvaluationContext.parseColor()
usedColor.parse()
which usedparseCssColor()
.Color.parse()
is also used infunction
expressions.The fixes for the issues were:
parseCssColor()
, since we probably want the convenience of using an object literal to initialize it, I opted to use the previously introduced (Fixvalidate_object
crashing when object prototype keys used in style's objects #1028)getOwn()
utility to ensure that only the literal's keys are tested.EvaluationContext.parseColor()
, the_parseColorCache
was previously initialized to an empty object literal{}
. Since there was no need for the ergonomics of using a literal, I replaced it withObject.create(null)
which creates an object without a prototype (note:{}
is syntactic sugar forObject.create(Object.prototype)
).The ideal solution for this would be to systematically use a
Map
if the key is user-controlled, but I did not find any uses of it from the codebase and assumed that the library targets ES5 compatibility.Launch Checklist
CHANGELOG.md
under the## main
section.