--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -2900,28 +2900,31 @@ CanvasRenderingContext2D::UpdateFilter()
sThisContextHadItsFilterUpdated = true;
}
// The filter might reference an SVG filter that is declared inside this
// document. Flush frames so that we'll have an nsSVGFilterFrame to work
// with.
presShell->FlushPendingNotifications(Flush_Frames);
+ bool sourceGraphicIsTainted =
+ (mCanvasElement && mCanvasElement->IsWriteOnly());
+
CurrentState().filter =
nsFilterInstance::GetFilterDescription(mCanvasElement,
CurrentState().filterChain,
+ sourceGraphicIsTainted,
CanvasUserSpaceMetrics(GetSize(),
CurrentState().fontFont,
CurrentState().fontLanguage,
CurrentState().fontExplicitLanguage,
presShell->GetPresContext()),
gfxRect(0, 0, mWidth, mHeight),
CurrentState().filterAdditionalImages);
- CurrentState().filterSourceGraphicTainted =
- (mCanvasElement && mCanvasElement->IsWriteOnly());
+ CurrentState().filterSourceGraphicTainted = sourceGraphicIsTainted;
}
//
// rects
//
static bool
ValidateRect(double& aX, double& aY, double& aWidth, double& aHeight, bool aIsZeroSizeValid)
--- a/layout/svg/nsCSSFilterInstance.cpp
+++ b/layout/svg/nsCSSFilterInstance.cpp
@@ -35,60 +35,81 @@ nsCSSFilterInstance::nsCSSFilterInstance
: mFilter(aFilter)
, mShadowFallbackColor(aShadowFallbackColor)
, mTargetBoundsInFilterSpace(aTargetBoundsInFilterSpace)
, mFrameSpaceInCSSPxToFilterSpaceTransform(aFrameSpaceInCSSPxToFilterSpaceTransform)
{
}
nsresult
-nsCSSFilterInstance::BuildPrimitives(nsTArray<FilterPrimitiveDescription>& aPrimitiveDescrs)
+nsCSSFilterInstance::BuildPrimitives(nsTArray<FilterPrimitiveDescription>& aPrimitiveDescrs,
+ bool aInputIsTainted)
{
FilterPrimitiveDescription descr;
nsresult result;
switch(mFilter.GetType()) {
case NS_STYLE_FILTER_BLUR:
- descr = CreatePrimitiveDescription(PrimitiveType::GaussianBlur, aPrimitiveDescrs);
+ descr = CreatePrimitiveDescription(PrimitiveType::GaussianBlur,
+ aPrimitiveDescrs,
+ aInputIsTainted);
result = SetAttributesForBlur(descr);
break;
case NS_STYLE_FILTER_BRIGHTNESS:
- descr = CreatePrimitiveDescription(PrimitiveType::ComponentTransfer, aPrimitiveDescrs);
+ descr = CreatePrimitiveDescription(PrimitiveType::ComponentTransfer,
+ aPrimitiveDescrs,
+ aInputIsTainted);
result = SetAttributesForBrightness(descr);
break;
case NS_STYLE_FILTER_CONTRAST:
- descr = CreatePrimitiveDescription(PrimitiveType::ComponentTransfer, aPrimitiveDescrs);
+ descr = CreatePrimitiveDescription(PrimitiveType::ComponentTransfer,
+ aPrimitiveDescrs,
+ aInputIsTainted);
result = SetAttributesForContrast(descr);
break;
case NS_STYLE_FILTER_DROP_SHADOW:
- descr = CreatePrimitiveDescription(PrimitiveType::DropShadow, aPrimitiveDescrs);
+ descr = CreatePrimitiveDescription(PrimitiveType::DropShadow,
+ aPrimitiveDescrs,
+ aInputIsTainted);
result = SetAttributesForDropShadow(descr);
break;
case NS_STYLE_FILTER_GRAYSCALE:
- descr = CreatePrimitiveDescription(PrimitiveType::ColorMatrix, aPrimitiveDescrs);
+ descr = CreatePrimitiveDescription(PrimitiveType::ColorMatrix,
+ aPrimitiveDescrs,
+ aInputIsTainted);
result = SetAttributesForGrayscale(descr);
break;
case NS_STYLE_FILTER_HUE_ROTATE:
- descr = CreatePrimitiveDescription(PrimitiveType::ColorMatrix, aPrimitiveDescrs);
+ descr = CreatePrimitiveDescription(PrimitiveType::ColorMatrix,
+ aPrimitiveDescrs,
+ aInputIsTainted);
result = SetAttributesForHueRotate(descr);
break;
case NS_STYLE_FILTER_INVERT:
- descr = CreatePrimitiveDescription(PrimitiveType::ComponentTransfer, aPrimitiveDescrs);
+ descr = CreatePrimitiveDescription(PrimitiveType::ComponentTransfer,
+ aPrimitiveDescrs,
+ aInputIsTainted);
result = SetAttributesForInvert(descr);
break;
case NS_STYLE_FILTER_OPACITY:
- descr = CreatePrimitiveDescription(PrimitiveType::ComponentTransfer, aPrimitiveDescrs);
+ descr = CreatePrimitiveDescription(PrimitiveType::ComponentTransfer,
+ aPrimitiveDescrs,
+ aInputIsTainted);
result = SetAttributesForOpacity(descr);
break;
case NS_STYLE_FILTER_SATURATE:
- descr = CreatePrimitiveDescription(PrimitiveType::ColorMatrix, aPrimitiveDescrs);
+ descr = CreatePrimitiveDescription(PrimitiveType::ColorMatrix,
+ aPrimitiveDescrs,
+ aInputIsTainted);
result = SetAttributesForSaturate(descr);
break;
case NS_STYLE_FILTER_SEPIA:
- descr = CreatePrimitiveDescription(PrimitiveType::ColorMatrix, aPrimitiveDescrs);
+ descr = CreatePrimitiveDescription(PrimitiveType::ColorMatrix,
+ aPrimitiveDescrs,
+ aInputIsTainted);
result = SetAttributesForSepia(descr);
break;
default:
NS_NOTREACHED("not a valid CSS filter type");
return NS_ERROR_FAILURE;
}
if (NS_FAILED(result)) {
@@ -101,21 +122,22 @@ nsCSSFilterInstance::BuildPrimitives(nsT
// Add this primitive to the filter chain.
aPrimitiveDescrs.AppendElement(descr);
return NS_OK;
}
FilterPrimitiveDescription
nsCSSFilterInstance::CreatePrimitiveDescription(PrimitiveType aType,
- const nsTArray<FilterPrimitiveDescription>& aPrimitiveDescrs) {
+ const nsTArray<FilterPrimitiveDescription>& aPrimitiveDescrs,
+ bool aInputIsTainted) {
FilterPrimitiveDescription descr(aType);
int32_t inputIndex = GetLastResultIndex(aPrimitiveDescrs);
descr.SetInputPrimitive(0, inputIndex);
- descr.SetIsTainted(inputIndex < 0 ? true : aPrimitiveDescrs[inputIndex].IsTainted());
+ descr.SetIsTainted(inputIndex < 0 ? aInputIsTainted : aPrimitiveDescrs[inputIndex].IsTainted());
descr.SetInputColorSpace(0, ColorSpace::SRGB);
descr.SetOutputColorSpace(ColorSpace::SRGB);
return descr;
}
nsresult
nsCSSFilterInstance::SetAttributesForBlur(FilterPrimitiveDescription& aDescr)
{
--- a/layout/svg/nsCSSFilterInstance.h
+++ b/layout/svg/nsCSSFilterInstance.h
@@ -45,25 +45,35 @@ public:
nscolor aShadowFallbackColor,
const nsIntRect& aTargetBoundsInFilterSpace,
const gfxMatrix& aFrameSpaceInCSSPxToFilterSpaceTransform);
/**
* Creates at least one new FilterPrimitiveDescription based on the filter
* from the style system. Appends the new FilterPrimitiveDescription(s) to the
* aPrimitiveDescrs list.
+ * aInputIsTainted describes whether the input to this filter is tainted, i.e.
+ * whether it contains security-sensitive content. This is needed to propagate
+ * taintedness to the FilterPrimitive that take tainted inputs. Something being
+ * tainted means that it contains security sensitive content.
+ * The input to this filter is the previous filter's output, i.e. the last
+ * element in aPrimitiveDescrs, or the SourceGraphic input if this is the first
+ * filter in the filter chain.
*/
- nsresult BuildPrimitives(nsTArray<FilterPrimitiveDescription>& aPrimitiveDescrs);
+ nsresult BuildPrimitives(nsTArray<FilterPrimitiveDescription>& aPrimitiveDescrs,
+ bool aInputIsTainted);
private:
/**
* Returns a new FilterPrimitiveDescription with its basic properties set up.
+ * See the comment above BuildPrimitives for the meaning of aInputIsTainted.
*/
FilterPrimitiveDescription CreatePrimitiveDescription(PrimitiveType aType,
- const nsTArray<FilterPrimitiveDescription>& aPrimitiveDescrs);
+ const nsTArray<FilterPrimitiveDescription>& aPrimitiveDescrs,
+ bool aInputIsTainted);
/**
* Sets aDescr's attributes using the style info in mFilter.
*/
nsresult SetAttributesForBlur(FilterPrimitiveDescription& aDescr);
nsresult SetAttributesForBrightness(FilterPrimitiveDescription& aDescr);
nsresult SetAttributesForContrast(FilterPrimitiveDescription& aDescr);
nsresult SetAttributesForDropShadow(FilterPrimitiveDescription& aDescr);
--- a/layout/svg/nsFilterInstance.cpp
+++ b/layout/svg/nsFilterInstance.cpp
@@ -27,24 +27,25 @@
using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::gfx;
FilterDescription
nsFilterInstance::GetFilterDescription(nsIContent* aFilteredElement,
const nsTArray<nsStyleFilter>& aFilterChain,
+ bool aFilterInputIsTainted,
const UserSpaceMetrics& aMetrics,
const gfxRect& aBBox,
nsTArray<RefPtr<SourceSurface>>& aOutAdditionalImages)
{
gfxMatrix unused; // aPaintTransform arg not used since we're not painting
nsFilterInstance instance(nullptr, aFilteredElement, aMetrics,
- aFilterChain, nullptr, unused,
- nullptr, nullptr, nullptr, &aBBox);
+ aFilterChain, aFilterInputIsTainted, nullptr,
+ unused, nullptr, nullptr, nullptr, &aBBox);
if (!instance.IsInitialized()) {
return FilterDescription();
}
return instance.ExtractDescriptionAndAdditionalImages(aOutAdditionalImages);
}
static UniquePtr<UserSpaceMetrics>
UserSpaceMetricsForFrame(nsIFrame* aFrame)
@@ -60,19 +61,21 @@ nsresult
nsFilterInstance::PaintFilteredFrame(nsIFrame *aFilteredFrame,
DrawTarget* aDrawTarget,
const gfxMatrix& aTransform,
nsSVGFilterPaintCallback *aPaintCallback,
const nsRegion *aDirtyArea)
{
auto& filterChain = aFilteredFrame->StyleEffects()->mFilters;
UniquePtr<UserSpaceMetrics> metrics = UserSpaceMetricsForFrame(aFilteredFrame);
+ // Hardcode InputIsTainted to true because we don't want JS to be able to
+ // read the rendered contents of aFilteredFrame.
nsFilterInstance instance(aFilteredFrame, aFilteredFrame->GetContent(), *metrics,
- filterChain, aPaintCallback, aTransform,
- aDirtyArea, nullptr, nullptr, nullptr);
+ filterChain, /* InputIsTainted */ true, aPaintCallback,
+ aTransform, aDirtyArea, nullptr, nullptr, nullptr);
if (!instance.IsInitialized()) {
return NS_OK;
}
return instance.Render(aDrawTarget);
}
nsRegion
nsFilterInstance::GetPostFilterDirtyArea(nsIFrame *aFilteredFrame,
@@ -80,19 +83,21 @@ nsFilterInstance::GetPostFilterDirtyArea
{
if (aPreFilterDirtyRegion.IsEmpty()) {
return nsRegion();
}
gfxMatrix unused; // aPaintTransform arg not used since we're not painting
auto& filterChain = aFilteredFrame->StyleEffects()->mFilters;
UniquePtr<UserSpaceMetrics> metrics = UserSpaceMetricsForFrame(aFilteredFrame);
+ // Hardcode InputIsTainted to true because we don't want JS to be able to
+ // read the rendered contents of aFilteredFrame.
nsFilterInstance instance(aFilteredFrame, aFilteredFrame->GetContent(), *metrics,
- filterChain, nullptr, unused, nullptr,
- &aPreFilterDirtyRegion);
+ filterChain, /* InputIsTainted */ true, nullptr, unused,
+ nullptr, &aPreFilterDirtyRegion);
if (!instance.IsInitialized()) {
return nsRegion();
}
// We've passed in the source's dirty area so the instance knows about it.
// Now we can ask the instance to compute the area of the filter output
// that's dirty.
return instance.ComputePostFilterDirtyRegion();
@@ -100,18 +105,20 @@ nsFilterInstance::GetPostFilterDirtyArea
nsRegion
nsFilterInstance::GetPreFilterNeededArea(nsIFrame *aFilteredFrame,
const nsRegion& aPostFilterDirtyRegion)
{
gfxMatrix unused; // aPaintTransform arg not used since we're not painting
auto& filterChain = aFilteredFrame->StyleEffects()->mFilters;
UniquePtr<UserSpaceMetrics> metrics = UserSpaceMetricsForFrame(aFilteredFrame);
+ // Hardcode InputIsTainted to true because we don't want JS to be able to
+ // read the rendered contents of aFilteredFrame.
nsFilterInstance instance(aFilteredFrame, aFilteredFrame->GetContent(), *metrics,
- filterChain, nullptr, unused,
+ filterChain, /* InputIsTainted */ true, nullptr, unused,
&aPostFilterDirtyRegion);
if (!instance.IsInitialized()) {
return nsRect();
}
// Now we can ask the instance to compute the area of the source
// that's needed.
return instance.ComputeSourceNeededRect();
@@ -131,31 +138,34 @@ nsFilterInstance::GetPostFilterBounds(ns
if (aPreFilterBounds) {
preFilterRegion = *aPreFilterBounds;
preFilterRegionPtr = &preFilterRegion;
}
gfxMatrix unused; // aPaintTransform arg not used since we're not painting
auto& filterChain = aFilteredFrame->StyleEffects()->mFilters;
UniquePtr<UserSpaceMetrics> metrics = UserSpaceMetricsForFrame(aFilteredFrame);
+ // Hardcode InputIsTainted to true because we don't want JS to be able to
+ // read the rendered contents of aFilteredFrame.
nsFilterInstance instance(aFilteredFrame, aFilteredFrame->GetContent(), *metrics,
- filterChain, nullptr, unused, nullptr,
- preFilterRegionPtr, aPreFilterBounds,
+ filterChain, /* InputIsTainted */ true, nullptr, unused,
+ nullptr, preFilterRegionPtr, aPreFilterBounds,
aOverrideBBox);
if (!instance.IsInitialized()) {
return nsRect();
}
return instance.ComputePostFilterExtents();
}
nsFilterInstance::nsFilterInstance(nsIFrame *aTargetFrame,
nsIContent* aTargetContent,
const UserSpaceMetrics& aMetrics,
const nsTArray<nsStyleFilter>& aFilterChain,
+ bool aFilterInputIsTainted,
nsSVGFilterPaintCallback *aPaintCallback,
const gfxMatrix& aPaintTransform,
const nsRegion *aPostFilterDirtyRegion,
const nsRegion *aPreFilterDirtyRegion,
const nsRect *aPreFilterVisualOverflowRectOverride,
const gfxRect *aOverrideBBox)
: mTargetFrame(aTargetFrame)
, mTargetContent(aTargetContent)
@@ -208,17 +218,17 @@ nsFilterInstance::nsFilterInstance(nsIFr
FrameSpaceToFilterSpace(aPreFilterVisualOverflowRectOverride);
} else if (mTargetFrame) {
nsRect preFilterVOR = mTargetFrame->GetPreEffectsVisualOverflowRect();
targetBounds = FrameSpaceToFilterSpace(&preFilterVOR);
}
mTargetBounds.UnionRect(mTargetBBoxInFilterSpace, targetBounds);
// Build the filter graph.
- rv = BuildPrimitives(aFilterChain, aTargetFrame);
+ rv = BuildPrimitives(aFilterChain, aTargetFrame, aFilterInputIsTainted);
if (NS_FAILED(rv)) {
return;
}
if (mPrimitiveDescriptions.IsEmpty()) {
// Nothing should be rendered.
return;
}
@@ -269,66 +279,72 @@ nsFilterInstance::FilterSpaceToUserSpace
gfxRect userSpaceRect = aFilterSpaceRect;
userSpaceRect.Scale(mFilterSpaceToUserSpaceScale.width,
mFilterSpaceToUserSpaceScale.height);
return userSpaceRect;
}
nsresult
nsFilterInstance::BuildPrimitives(const nsTArray<nsStyleFilter>& aFilterChain,
- nsIFrame* aTargetFrame)
+ nsIFrame* aTargetFrame,
+ bool aFilterInputIsTainted)
{
NS_ASSERTION(!mPrimitiveDescriptions.Length(),
"expected to start building primitives from scratch");
for (uint32_t i = 0; i < aFilterChain.Length(); i++) {
- nsresult rv = BuildPrimitivesForFilter(aFilterChain[i], aTargetFrame);
+ bool inputIsTainted =
+ mPrimitiveDescriptions.IsEmpty() ? aFilterInputIsTainted :
+ mPrimitiveDescriptions.LastElement().IsTainted();
+ nsresult rv = BuildPrimitivesForFilter(aFilterChain[i], aTargetFrame, inputIsTainted);
if (NS_FAILED(rv)) {
return rv;
}
}
mFilterDescription = FilterDescription(mPrimitiveDescriptions);
return NS_OK;
}
nsresult
nsFilterInstance::BuildPrimitivesForFilter(const nsStyleFilter& aFilter,
- nsIFrame* aTargetFrame)
+ nsIFrame* aTargetFrame,
+ bool aInputIsTainted)
{
NS_ASSERTION(mUserSpaceToFilterSpaceScale.width > 0.0f &&
mFilterSpaceToUserSpaceScale.height > 0.0f,
"scale factors between spaces should be positive values");
if (aFilter.GetType() == NS_STYLE_FILTER_URL) {
// Build primitives for an SVG filter.
nsSVGFilterInstance svgFilterInstance(aFilter, aTargetFrame,
mTargetContent,
mMetrics, mTargetBBox,
mUserSpaceToFilterSpaceScale,
mFilterSpaceToUserSpaceScale);
if (!svgFilterInstance.IsInitialized()) {
return NS_ERROR_FAILURE;
}
- return svgFilterInstance.BuildPrimitives(mPrimitiveDescriptions, mInputImages);
+ return svgFilterInstance.BuildPrimitives(mPrimitiveDescriptions, mInputImages,
+ aInputIsTainted);
}
// Build primitives for a CSS filter.
// If we don't have a frame, use opaque black for shadows with unspecified
// shadow colors.
nscolor shadowFallbackColor =
mTargetFrame ? mTargetFrame->StyleColor()->mColor : NS_RGB(0,0,0);
nsCSSFilterInstance cssFilterInstance(aFilter, shadowFallbackColor,
mTargetBounds,
mFrameSpaceInCSSPxToFilterSpaceTransform);
- return cssFilterInstance.BuildPrimitives(mPrimitiveDescriptions);
+ return cssFilterInstance.BuildPrimitives(mPrimitiveDescriptions, aInputIsTainted);
}
void
nsFilterInstance::ComputeNeededBoxes()
{
if (mPrimitiveDescriptions.IsEmpty())
return;
--- a/layout/svg/nsFilterInstance.h
+++ b/layout/svg/nsFilterInstance.h
@@ -55,22 +55,29 @@ class nsFilterInstance
typedef mozilla::gfx::FilterPrimitiveDescription FilterPrimitiveDescription;
typedef mozilla::gfx::FilterDescription FilterDescription;
typedef mozilla::dom::UserSpaceMetrics UserSpaceMetrics;
public:
/**
* Create a FilterDescription for the supplied filter. All coordinates in
* the description are in filter space.
+ * @param aFilterInputIsTainted Describes whether the SourceImage / SourceAlpha
+ * input is tainted. This affects whether feDisplacementMap will respect
+ * the filter input as its map input, and it affects the IsTainted() state
+ * on the filter primitives in the FilterDescription. "Tainted" is a term
+ * from the filters spec and means security-sensitive content, i.e. pixels
+ * that JS should not be able to read in any way.
* @param aOutAdditionalImages Will contain additional images needed to
* render the filter (from feImage primitives).
* @return A FilterDescription describing the filter.
*/
static FilterDescription GetFilterDescription(nsIContent* aFilteredElement,
const nsTArray<nsStyleFilter>& aFilterChain,
+ bool aFilterInputIsTainted,
const UserSpaceMetrics& aMetrics,
const gfxRect& aBBox,
nsTArray<RefPtr<SourceSurface>>& aOutAdditionalImages);
/**
* Paint the given filtered frame.
* @param aDirtyArea The area than needs to be painted, in aFilteredFrame's
* frame space (i.e. relative to its origin, the top-left corner of its
@@ -113,16 +120,19 @@ public:
const nsRect *aPreFilterBounds = nullptr);
/**
* @param aTargetFrame The frame of the filtered element under consideration,
* may be null.
* @param aTargetContent The filtered element itself.
* @param aMetrics The metrics to resolve SVG lengths against.
* @param aFilterChain The list of filters to apply.
+ * @param aFilterInputIsTainted Describes whether the SourceImage / SourceAlpha
+ * input is tainted. This affects whether feDisplacementMap will respect
+ * the filter input as its map input.
* @param aPaintCallback [optional] The callback that Render() should use to
* paint. Only required if you will call Render().
* @param aPaintTransform The transform to apply to convert to
* aTargetFrame's SVG user space. Only used when painting.
* @param aPostFilterDirtyRegion [optional] The post-filter area
* that has to be repainted, in app units. Only required if you will
* call ComputeSourceNeededRect() or Render().
* @param aPreFilterDirtyRegion [optional] The pre-filter area of
@@ -132,16 +142,17 @@ public:
* visual overflow rect for the target element.
* @param aOverrideBBox [optional] Use a different SVG bbox for the target
* element. Must be non-null if aTargetFrame is null.
*/
nsFilterInstance(nsIFrame *aTargetFrame,
nsIContent* aTargetContent,
const UserSpaceMetrics& aMetrics,
const nsTArray<nsStyleFilter>& aFilterChain,
+ bool aFilterInputIsTainted,
nsSVGFilterPaintCallback *aPaintCallback,
const gfxMatrix& aPaintTransform,
const nsRegion *aPostFilterDirtyRegion = nullptr,
const nsRegion *aPreFilterDirtyRegion = nullptr,
const nsRect *aOverridePreFilterVisualOverflowRect = nullptr,
const gfxRect *aOverrideBBox = nullptr);
/**
@@ -231,28 +242,32 @@ private:
* Creates the SourceSurface for the SourceGraphic graph node, paints its
* contents, and assigns it to mSourceGraphic.mSourceSurface.
*/
nsresult BuildSourceImage(DrawTarget* aTargetDT);
/**
* Build the list of FilterPrimitiveDescriptions that describes the filter's
* filter primitives and their connections. This populates
- * mPrimitiveDescriptions and mInputImages.
+ * mPrimitiveDescriptions and mInputImages. aFilterInputIsTainted describes
+ * whether the SourceGraphic is tainted.
*/
nsresult BuildPrimitives(const nsTArray<nsStyleFilter>& aFilterChain,
- nsIFrame* aTargetFrame);
+ nsIFrame* aTargetFrame,
+ bool aFilterInputIsTainted);
/**
* Add to the list of FilterPrimitiveDescriptions for a particular SVG
- * reference filter or CSS filter. This populates mPrimitiveDescrs and
- * mInputImages.
+ * reference filter or CSS filter. This populates mPrimitiveDescriptions and
+ * mInputImages. aInputIsTainted describes whether the input to aFilter is
+ * tainted.
*/
nsresult BuildPrimitivesForFilter(const nsStyleFilter& aFilter,
- nsIFrame* aTargetFrame);
+ nsIFrame* aTargetFrame,
+ bool aInputIsTainted);
/**
* Computes the filter space bounds of the areas that we actually *need* from
* the filter sources, based on the value of mPostFilterDirtyRegion.
* This sets mNeededBounds on the corresponding SourceInfo structs.
*/
void ComputeNeededBoxes();
--- a/layout/svg/nsSVGFilterInstance.cpp
+++ b/layout/svg/nsSVGFilterInstance.cpp
@@ -361,33 +361,20 @@ nsSVGFilterInstance::GetSourceIndices(ns
return NS_ERROR_FAILURE;
}
aSourceIndices.AppendElement(sourceIndex);
}
return NS_OK;
}
-static bool
-IsFilterInputTainted(nsIContent* aElement)
-{
- // When the filter is applied during canvas drawing, we might be allowed to
- // read from the canvas.
- if (HTMLCanvasElement* canvas =
- HTMLCanvasElement::FromContentOrNull(aElement)) {
- return canvas->IsWriteOnly();
- }
-
- // Always treat normal filtered elements as tainted.
- return true;
-}
-
nsresult
nsSVGFilterInstance::BuildPrimitives(nsTArray<FilterPrimitiveDescription>& aPrimitiveDescrs,
- nsTArray<RefPtr<SourceSurface>>& aInputImages)
+ nsTArray<RefPtr<SourceSurface>>& aInputImages,
+ bool aInputIsTainted)
{
mSourceGraphicIndex = GetLastResultIndex(aPrimitiveDescrs);
// Clip previous filter's output to this filter's filter region.
if (mSourceGraphicIndex >= 0) {
FilterPrimitiveDescription& sourceDescr = aPrimitiveDescrs[mSourceGraphicIndex];
sourceDescr.SetPrimitiveSubregion(sourceDescr.PrimitiveSubregion().Intersect(mFilterSpaceBounds));
}
@@ -405,34 +392,32 @@ nsSVGFilterInstance::BuildPrimitives(nsT
}
// Maps source image name to source index.
nsDataHashtable<nsStringHashKey, int32_t> imageTable(8);
// The principal that we check principals of any loaded images against.
nsCOMPtr<nsIPrincipal> principal = mTargetContent->NodePrincipal();
- bool filterInputIsTainted = IsFilterInputTainted(mTargetContent);
-
for (uint32_t primitiveElementIndex = 0;
primitiveElementIndex < primitives.Length();
++primitiveElementIndex) {
nsSVGFE* filter = primitives[primitiveElementIndex];
AutoTArray<int32_t,2> sourceIndices;
nsresult rv = GetSourceIndices(filter, aPrimitiveDescrs, imageTable, sourceIndices);
if (NS_FAILED(rv)) {
return rv;
}
IntRect primitiveSubregion =
ComputeFilterPrimitiveSubregion(filter, aPrimitiveDescrs, sourceIndices);
nsTArray<bool> sourcesAreTainted;
- GetInputsAreTainted(aPrimitiveDescrs, sourceIndices, filterInputIsTainted, sourcesAreTainted);
+ GetInputsAreTainted(aPrimitiveDescrs, sourceIndices, aInputIsTainted, sourcesAreTainted);
FilterPrimitiveDescription descr =
filter->GetPrimitiveDescription(this, primitiveSubregion, sourcesAreTainted, aInputImages);
descr.SetIsTainted(filter->OutputIsTainted(sourcesAreTainted, principal));
descr.SetFilterSpaceBounds(mFilterSpaceBounds);
descr.SetPrimitiveSubregion(primitiveSubregion.Intersect(descr.FilterSpaceBounds()));
--- a/layout/svg/nsSVGFilterInstance.h
+++ b/layout/svg/nsSVGFilterInstance.h
@@ -93,19 +93,27 @@ public:
*/
bool IsInitialized() const { return mInitialized; }
/**
* Iterates through the <filter> element's primitive elements, creating a
* FilterPrimitiveDescription for each one. Appends the new
* FilterPrimitiveDescription(s) to the aPrimitiveDescrs list. Also, appends
* new images from feImage filter primitive elements to the aInputImages list.
+ * aInputIsTainted describes whether the input to this filter is tainted, i.e.
+ * whether it contains security-sensitive content. This is needed to propagate
+ * taintedness to the FilterPrimitive that take tainted inputs. Something being
+ * tainted means that it contains security sensitive content.
+ * The input to this filter is the previous filter's output, i.e. the last
+ * element in aPrimitiveDescrs, or the SourceGraphic input if this is the first
+ * filter in the filter chain.
*/
nsresult BuildPrimitives(nsTArray<FilterPrimitiveDescription>& aPrimitiveDescrs,
- nsTArray<RefPtr<SourceSurface>>& aInputImages);
+ nsTArray<RefPtr<SourceSurface>>& aInputImages,
+ bool aInputIsTainted);
/**
* Returns the user specified "filter region", in the filtered element's user
* space, after it has been adjusted out (if necessary) so that its edges
* coincide with pixel boundaries of the offscreen surface into which the
* filtered output would/will be painted.
*/
gfxRect GetFilterRegion() const { return mUserSpaceBounds; }