Bug 234558

Summary: Gradient encode/decode does not validate that the serialized stops were sorted
Product: WebKit Reporter: Sam Weinig <sam>
Component: PlatformAssignee: Sam Weinig <sam>
Status: RESOLVED FIXED    
Severity: Normal CC: changseok, darin, dino, esprehn+autocc, ews-watchlist, fmalita, glenn, gyuyoung.kim, kondapallykalyan, mitz, pdr, sabouhallawa, schenney, sergio, simon.fraser, thorton, webkit-bug-importer
Priority: P2 Keywords: InRadar
Version: WebKit Nightly Build   
Hardware: Unspecified   
OS: Unspecified   
Attachments:
Description Flags
Patch none

Description Sam Weinig 2021-12-21 04:24:07 PST
The Gradient encoder/decoder currently encodes the stopsSorted bit and on decode assumes that bit can be trusted without verifying validating that in fact the stops are sorted.
Comment 1 Sam Weinig 2021-12-21 04:25:29 PST
I don't believe there is any current issue with this, as it looks like the underlying graphics libraries do their own sort of the stops (which begs the question why are we sorting them), but leaving the object in this invalid state is non-the-less a bad idea.
Comment 2 Sam Weinig 2021-12-21 09:59:56 PST
Created attachment 447728 [details]
Patch
Comment 3 EWS 2021-12-21 11:17:17 PST
Committed r287324 (245474@main): <https://commits.webkit.org/245474@main>

All reviewed patches have been landed. Closing bug and clearing flags on attachment 447728 [details].
Comment 4 Radar WebKit Bug Importer 2021-12-21 11:18:19 PST
<rdar://problem/86777463>
Comment 5 Darin Adler 2021-12-21 11:52:33 PST
Comment on attachment 447728 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=447728&action=review

Sure does look nice

> Source/WebCore/rendering/svg/RenderSVGResourceGradient.cpp:234
> +    Gradient::ColorStopVector result;
> +    result.reserveInitialCapacity(stops.size());
>      for (auto& stop : stops)
> -        gradient.addColorStop({ stop.offset, style.colorByApplyingColorFilter(stop.color) });
> +        result.uncheckedAppend({ stop.offset, style.colorByApplyingColorFilter(stop.color) });
> +    return result;

Seems like we could use Vector::map here and make this a bit more elegant

> Source/WebCore/rendering/svg/RenderSVGResourceLinearGradient.cpp:58
> +        Gradient::LinearData { startPoint(m_attributes), endPoint(m_attributes) },
> +        ColorInterpolationMethod { ColorInterpolationMethod::SRGB { }, AlphaPremultiplication::Unpremultiplied },

Can any of the type names be omitted? Maybe it would make the code more confusing, but I like the idea of making things a little more terse

> Source/WebCore/rendering/svg/RenderSVGResourceRadialGradient.cpp:69
> +        Gradient::RadialData { focalPoint(m_attributes), centerPoint(m_attributes), focalRadius(m_attributes), radius(m_attributes), 1 },
> +        ColorInterpolationMethod { ColorInterpolationMethod::SRGB { }, AlphaPremultiplication::Unpremultiplied },

Ditto.
Comment 6 Sam Weinig 2021-12-21 17:39:18 PST
(In reply to Darin Adler from comment #5)
> Comment on attachment 447728 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=447728&action=review
> 
> Sure does look nice
> 
> > Source/WebCore/rendering/svg/RenderSVGResourceGradient.cpp:234
> > +    Gradient::ColorStopVector result;
> > +    result.reserveInitialCapacity(stops.size());
> >      for (auto& stop : stops)
> > -        gradient.addColorStop({ stop.offset, style.colorByApplyingColorFilter(stop.color) });
> > +        result.uncheckedAppend({ stop.offset, style.colorByApplyingColorFilter(stop.color) });
> > +    return result;
> 
> Seems like we could use Vector::map here and make this a bit more elegant

Alas, I couldn't figure out how to make Vector::map() work with ColorStopVector due to the inline capacity. ColorStopVector == Vector<GradientColorStop, 2>.

> 
> > Source/WebCore/rendering/svg/RenderSVGResourceLinearGradient.cpp:58
> > +        Gradient::LinearData { startPoint(m_attributes), endPoint(m_attributes) },
> > +        ColorInterpolationMethod { ColorInterpolationMethod::SRGB { }, AlphaPremultiplication::Unpremultiplied },
> 
> Can any of the type names be omitted? Maybe it would make the code more
> confusing, but I like the idea of making things a little more terse
> 
> > Source/WebCore/rendering/svg/RenderSVGResourceRadialGradient.cpp:69
> > +        Gradient::RadialData { focalPoint(m_attributes), centerPoint(m_attributes), focalRadius(m_attributes), radius(m_attributes), 1 },
> > +        ColorInterpolationMethod { ColorInterpolationMethod::SRGB { }, AlphaPremultiplication::Unpremultiplied },
> 
> Ditto.

Yeah, not sure why I added the extra ColorInterpolationMethod in there. Will remove.
Comment 7 Sam Weinig 2021-12-21 17:54:53 PST
> > > Source/WebCore/rendering/svg/RenderSVGResourceLinearGradient.cpp:58
> > > +        Gradient::LinearData { startPoint(m_attributes), endPoint(m_attributes) },
> > > +        ColorInterpolationMethod { ColorInterpolationMethod::SRGB { }, AlphaPremultiplication::Unpremultiplied },
> > 
> > Can any of the type names be omitted? Maybe it would make the code more
> > confusing, but I like the idea of making things a little more terse
> > 
> > > Source/WebCore/rendering/svg/RenderSVGResourceRadialGradient.cpp:69
> > > +        Gradient::RadialData { focalPoint(m_attributes), centerPoint(m_attributes), focalRadius(m_attributes), radius(m_attributes), 1 },
> > > +        ColorInterpolationMethod { ColorInterpolationMethod::SRGB { }, AlphaPremultiplication::Unpremultiplied },
> > 
> > Ditto.
> 
> Yeah, not sure why I added the extra ColorInterpolationMethod in there. Will
> remove.

Will resolve these in https://bugs.webkit.org/show_bug.cgi?id=234583
Comment 8 Darin Adler 2021-12-24 09:05:10 PST
Comment on attachment 447728 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=447728&action=review

>>> Source/WebCore/rendering/svg/RenderSVGResourceGradient.cpp:234
>>> +    return result;
>> 
>> Seems like we could use Vector::map here and make this a bit more elegant
> 
> Alas, I couldn't figure out how to make Vector::map() work with ColorStopVector due to the inline capacity. ColorStopVector == Vector<GradientColorStop, 2>.

We can enhance Vector::map to make it a template that takes a type for the destination vector that defaults to the type of the source vector.
Comment 9 Sam Weinig 2021-12-25 18:46:33 PST
(In reply to Darin Adler from comment #8)
> Comment on attachment 447728 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=447728&action=review
> 
> >>> Source/WebCore/rendering/svg/RenderSVGResourceGradient.cpp:234
> >>> +    return result;
> >> 
> >> Seems like we could use Vector::map here and make this a bit more elegant
> > 
> > Alas, I couldn't figure out how to make Vector::map() work with ColorStopVector due to the inline capacity. ColorStopVector == Vector<GradientColorStop, 2>.
> 
> We can enhance Vector::map to make it a template that takes a type for the
> destination vector that defaults to the type of the source vector.

https://bugs.webkit.org/show_bug.cgi?id=234683