mirror of
https://github.com/servo/servo.git
synced 2025-07-24 15:50:21 +01:00
Implement proper origin checks for WebGL textures (fixes #21522)
This commit is contained in:
parent
e745050f3a
commit
8c100b23b1
13 changed files with 129 additions and 99 deletions
|
@ -247,8 +247,7 @@ impl CanvasRenderingContext2D {
|
||||||
canvas.origin_is_clean()
|
canvas.origin_is_clean()
|
||||||
}
|
}
|
||||||
CanvasImageSource::HTMLImageElement(image) => {
|
CanvasImageSource::HTMLImageElement(image) => {
|
||||||
let image_origin = image.get_origin().expect("Image's origin is missing");
|
image.same_origin(GlobalScope::entry().origin())
|
||||||
image_origin.same_origin(GlobalScope::entry().origin())
|
|
||||||
}
|
}
|
||||||
CanvasImageSource::CSSStyleValue(_) => true,
|
CanvasImageSource::CSSStyleValue(_) => true,
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,7 @@ use network_listener::{NetworkListener, PreInvoke};
|
||||||
use num_traits::ToPrimitive;
|
use num_traits::ToPrimitive;
|
||||||
use script_thread::ScriptThread;
|
use script_thread::ScriptThread;
|
||||||
use servo_url::ServoUrl;
|
use servo_url::ServoUrl;
|
||||||
use servo_url::origin::ImmutableOrigin;
|
use servo_url::origin::MutableOrigin;
|
||||||
use std::cell::{Cell, RefMut};
|
use std::cell::{Cell, RefMut};
|
||||||
use std::char;
|
use std::char;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
@ -1186,11 +1186,10 @@ impl HTMLImageElement {
|
||||||
useMapElements.map(|mapElem| mapElem.get_area_elements())
|
useMapElements.map(|mapElem| mapElem.get_area_elements())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_origin(&self) -> Option<ImmutableOrigin> {
|
pub fn same_origin(&self, origin: &MutableOrigin) -> bool {
|
||||||
match self.current_request.borrow_mut().final_url {
|
self.current_request.borrow_mut().final_url.as_ref().map_or(false, |url| {
|
||||||
Some(ref url) => Some(url.origin()),
|
url.scheme() == "data" || url.origin().same_origin(origin)
|
||||||
None => None
|
})
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,15 +13,16 @@ use canvas_traits::webgl::WebGLError::*;
|
||||||
use dom::bindings::codegen::Bindings::ANGLEInstancedArraysBinding::ANGLEInstancedArraysConstants;
|
use dom::bindings::codegen::Bindings::ANGLEInstancedArraysBinding::ANGLEInstancedArraysConstants;
|
||||||
use dom::bindings::codegen::Bindings::EXTBlendMinmaxBinding::EXTBlendMinmaxConstants;
|
use dom::bindings::codegen::Bindings::EXTBlendMinmaxBinding::EXTBlendMinmaxConstants;
|
||||||
use dom::bindings::codegen::Bindings::OESVertexArrayObjectBinding::OESVertexArrayObjectConstants;
|
use dom::bindings::codegen::Bindings::OESVertexArrayObjectBinding::OESVertexArrayObjectConstants;
|
||||||
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::{self, WebGLContextAttributes};
|
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding;
|
||||||
|
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::TexImageSource;
|
||||||
|
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLContextAttributes;
|
||||||
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
|
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
|
||||||
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextMethods;
|
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextMethods;
|
||||||
use dom::bindings::codegen::UnionTypes::ArrayBufferViewOrArrayBuffer;
|
use dom::bindings::codegen::UnionTypes::ArrayBufferViewOrArrayBuffer;
|
||||||
use dom::bindings::codegen::UnionTypes::Float32ArrayOrUnrestrictedFloatSequence;
|
use dom::bindings::codegen::UnionTypes::Float32ArrayOrUnrestrictedFloatSequence;
|
||||||
use dom::bindings::codegen::UnionTypes::ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement;
|
|
||||||
use dom::bindings::codegen::UnionTypes::Int32ArrayOrLongSequence;
|
use dom::bindings::codegen::UnionTypes::Int32ArrayOrLongSequence;
|
||||||
use dom::bindings::conversions::{DerivedFrom, ToJSValConvertible};
|
use dom::bindings::conversions::{DerivedFrom, ToJSValConvertible};
|
||||||
use dom::bindings::error::{Error, ErrorResult};
|
use dom::bindings::error::{Error, ErrorResult, Fallible};
|
||||||
use dom::bindings::inheritance::Castable;
|
use dom::bindings::inheritance::Castable;
|
||||||
use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object};
|
use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object};
|
||||||
use dom::bindings::root::{Dom, DomOnceCell, DomRoot, LayoutDom, MutNullableDom};
|
use dom::bindings::root::{Dom, DomOnceCell, DomRoot, LayoutDom, MutNullableDom};
|
||||||
|
@ -30,7 +31,7 @@ use dom::event::{Event, EventBubbles, EventCancelable};
|
||||||
use dom::htmlcanvaselement::HTMLCanvasElement;
|
use dom::htmlcanvaselement::HTMLCanvasElement;
|
||||||
use dom::htmlcanvaselement::utils as canvas_utils;
|
use dom::htmlcanvaselement::utils as canvas_utils;
|
||||||
use dom::htmliframeelement::HTMLIFrameElement;
|
use dom::htmliframeelement::HTMLIFrameElement;
|
||||||
use dom::node::{Node, NodeDamage, window_from_node};
|
use dom::node::{Node, NodeDamage, document_from_node, window_from_node};
|
||||||
use dom::webgl_extensions::WebGLExtensions;
|
use dom::webgl_extensions::WebGLExtensions;
|
||||||
use dom::webgl_validations::WebGLValidator;
|
use dom::webgl_validations::WebGLValidator;
|
||||||
use dom::webgl_validations::tex_image_2d::{CommonTexImage2DValidator, CommonTexImage2DValidatorResult};
|
use dom::webgl_validations::tex_image_2d::{CommonTexImage2DValidator, CommonTexImage2DValidatorResult};
|
||||||
|
@ -76,7 +77,6 @@ pub fn is_gles() -> bool {
|
||||||
cfg!(any(target_os = "android", target_os = "ios"))
|
cfg!(any(target_os = "android", target_os = "ios"))
|
||||||
}
|
}
|
||||||
|
|
||||||
type ImagePixelResult = Result<(Vec<u8>, Size2D<i32>, bool), ()>;
|
|
||||||
pub const MAX_UNIFORM_AND_ATTRIBUTE_LEN: usize = 256;
|
pub const MAX_UNIFORM_AND_ATTRIBUTE_LEN: usize = 256;
|
||||||
|
|
||||||
// From the GLES 2.0.25 spec, page 85:
|
// From the GLES 2.0.25 spec, page 85:
|
||||||
|
@ -490,21 +490,21 @@ impl WebGLRenderingContext {
|
||||||
|
|
||||||
fn get_image_pixels(
|
fn get_image_pixels(
|
||||||
&self,
|
&self,
|
||||||
source: ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement,
|
source: TexImageSource,
|
||||||
) -> ImagePixelResult {
|
) -> Fallible<Option<(Vec<u8>, Size2D<i32>, bool)>> {
|
||||||
// NOTE: Getting the pixels probably can be short-circuited if some
|
Ok(Some(match source {
|
||||||
// parameter is invalid.
|
TexImageSource::ImageData(image_data) => {
|
||||||
//
|
|
||||||
// Nontheless, since it's the error case, I'm not totally sure the
|
|
||||||
// complexity is worth it.
|
|
||||||
let (pixels, size, premultiplied) = match source {
|
|
||||||
ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement::ImageData(image_data) => {
|
|
||||||
(image_data.get_data_array(), image_data.get_size(), false)
|
(image_data.get_data_array(), image_data.get_size(), false)
|
||||||
},
|
},
|
||||||
ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement::HTMLImageElement(image) => {
|
TexImageSource::HTMLImageElement(image) => {
|
||||||
|
let document = document_from_node(&*self.canvas);
|
||||||
|
if !image.same_origin(document.origin()) {
|
||||||
|
return Err(Error::Security);
|
||||||
|
}
|
||||||
|
|
||||||
let img_url = match image.get_url() {
|
let img_url = match image.get_url() {
|
||||||
Some(url) => url,
|
Some(url) => url,
|
||||||
None => return Err(()),
|
None => return Ok(None),
|
||||||
};
|
};
|
||||||
|
|
||||||
let window = window_from_node(&*self.canvas);
|
let window = window_from_node(&*self.canvas);
|
||||||
|
@ -513,7 +513,7 @@ impl WebGLRenderingContext {
|
||||||
ImageResponse::Loaded(img, _) => img,
|
ImageResponse::Loaded(img, _) => img,
|
||||||
ImageResponse::PlaceholderLoaded(_, _) | ImageResponse::None |
|
ImageResponse::PlaceholderLoaded(_, _) | ImageResponse::None |
|
||||||
ImageResponse::MetadataLoaded(_)
|
ImageResponse::MetadataLoaded(_)
|
||||||
=> return Err(()),
|
=> return Ok(None),
|
||||||
};
|
};
|
||||||
|
|
||||||
let size = Size2D::new(img.width as i32, img.height as i32);
|
let size = Size2D::new(img.width as i32, img.height as i32);
|
||||||
|
@ -531,22 +531,23 @@ impl WebGLRenderingContext {
|
||||||
// TODO(emilio): Getting canvas data is implemented in CanvasRenderingContext2D,
|
// TODO(emilio): Getting canvas data is implemented in CanvasRenderingContext2D,
|
||||||
// but we need to refactor it moving it to `HTMLCanvasElement` and support
|
// but we need to refactor it moving it to `HTMLCanvasElement` and support
|
||||||
// WebGLContext (probably via GetPixels()).
|
// WebGLContext (probably via GetPixels()).
|
||||||
ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement::HTMLCanvasElement(canvas) => {
|
TexImageSource::HTMLCanvasElement(canvas) => {
|
||||||
|
if !canvas.origin_is_clean() {
|
||||||
|
return Err(Error::Security);
|
||||||
|
}
|
||||||
if let Some((mut data, size)) = canvas.fetch_all_data() {
|
if let Some((mut data, size)) = canvas.fetch_all_data() {
|
||||||
// Pixels got from Canvas have already alpha premultiplied
|
// Pixels got from Canvas have already alpha premultiplied
|
||||||
byte_swap(&mut data);
|
byte_swap(&mut data);
|
||||||
(data, size, true)
|
(data, size, true)
|
||||||
} else {
|
} else {
|
||||||
return Err(());
|
return Ok(None);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement::HTMLVideoElement(_) => {
|
TexImageSource::HTMLVideoElement(_) => {
|
||||||
// TODO: https://github.com/servo/servo/issues/6711
|
// TODO: https://github.com/servo/servo/issues/6711
|
||||||
return Err(());
|
return Ok(None);
|
||||||
}
|
}
|
||||||
};
|
}))
|
||||||
|
|
||||||
return Ok((pixels, size, premultiplied));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(emilio): Move this logic to a validator.
|
// TODO(emilio): Move this logic to a validator.
|
||||||
|
@ -3520,16 +3521,15 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
||||||
internal_format: u32,
|
internal_format: u32,
|
||||||
format: u32,
|
format: u32,
|
||||||
data_type: u32,
|
data_type: u32,
|
||||||
source: ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement,
|
source: TexImageSource,
|
||||||
) -> ErrorResult {
|
) -> ErrorResult {
|
||||||
if !self.extension_manager.is_tex_type_enabled(data_type) {
|
if !self.extension_manager.is_tex_type_enabled(data_type) {
|
||||||
return Ok(self.webgl_error(InvalidEnum));
|
return Ok(self.webgl_error(InvalidEnum));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get pixels from image source
|
let (pixels, size, premultiplied) = match self.get_image_pixels(source)? {
|
||||||
let (pixels, size, premultiplied) = match self.get_image_pixels(source) {
|
Some(triple) => triple,
|
||||||
Ok((pixels, size, premultiplied)) => (pixels, size, premultiplied),
|
None => return Ok(()),
|
||||||
Err(_) => return Ok(()),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let validator = TexImage2DValidator::new(self,
|
let validator = TexImage2DValidator::new(self,
|
||||||
|
@ -3677,11 +3677,11 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
||||||
yoffset: i32,
|
yoffset: i32,
|
||||||
format: u32,
|
format: u32,
|
||||||
data_type: u32,
|
data_type: u32,
|
||||||
source: ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement,
|
source: TexImageSource,
|
||||||
) -> ErrorResult {
|
) -> ErrorResult {
|
||||||
let (pixels, size, premultiplied) = match self.get_image_pixels(source) {
|
let (pixels, size, premultiplied) = match self.get_image_pixels(source)? {
|
||||||
Ok((pixels, size, premultiplied)) => (pixels, size, premultiplied),
|
Some(triple) => triple,
|
||||||
Err(_) => return Ok(()),
|
None => return Ok(()),
|
||||||
};
|
};
|
||||||
|
|
||||||
let validator = TexImage2DValidator::new(self, target, level, format,
|
let validator = TexImage2DValidator::new(self, target, level, format,
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
[security.dataURI.html]
|
|
||||||
type: testharness
|
|
||||||
[data: URIs do not count as different-origin, and do not taint the canvas]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
[toDataURL.jpeg.primarycolours.html]
|
|
||||||
type: testharness
|
|
||||||
[toDataURL with JPEG handles simple colours correctly]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
[toDataURL.png.complexcolours.html]
|
|
||||||
type: testharness
|
|
||||||
[toDataURL with PNG handles non-primary and non-solid colours correctly]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
[toDataURL.png.primarycolours.html]
|
|
||||||
type: testharness
|
|
||||||
[toDataURL with PNG handles simple colours correctly]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
[data-url.html]
|
|
||||||
type: testharness
|
|
||||||
[data URL image]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,3 +1,91 @@
|
||||||
[to-data-url-test.html]
|
[to-data-url-test.html]
|
||||||
bug: https://github.com/servo/servo/issues/21132
|
[WebGL test #12: should be 0,255,0,255\nat (0, 0) expected: 0,255,0,255 was 255,0,0,255]
|
||||||
expected: ERROR
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #18: should be 0,255,0,255\nat (0, 0) expected: 0,255,0,255 was 255,0,0,255]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #1: should be 255,0,0,255\nat (0, 8) expected: 255,0,0,255 was 0,255,0,255]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #4: should be 255,0,0,255\nat (0, 8) expected: 255,0,0,255 was 0,255,0,255]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #34: should be 255,0,0,255\nat (0, 256) expected: 255,0,0,255 was 0,255,0,255]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #24: should be 0,255,0,255\nat (0, 0) expected: 0,255,0,255 was 255,0,0,255]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #31: should be 255,0,0,255\nat (0, 256) expected: 255,0,0,255 was 0,255,0,255]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #10: should be 255,0,0,255\nat (0, 8) expected: 255,0,0,255 was 0,255,0,255]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #25: should be 255,0,0,255\nat (0, 128) expected: 255,0,0,255 was 0,255,0,255]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #40: should be 255,0,0,255\nat (0, 256) expected: 255,0,0,255 was 0,255,0,255]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #19: should be 255,0,0,255\nat (0, 128) expected: 255,0,0,255 was 0,255,0,255]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #9: should be 0,255,0,255\nat (0, 0) expected: 0,255,0,255 was 255,0,0,255]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #3: should be 0,255,0,255\nat (0, 0) expected: 0,255,0,255 was 255,0,0,255]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #43: should be 255,0,0,255\nat (0, 257) expected: 255,0,0,255 was 0,255,0,255]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #15: should be 0,255,0,255\nat (0, 0) expected: 0,255,0,255 was 255,0,0,255]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #16: should be 255,0,0,255\nat (0, 128) expected: 255,0,0,255 was 0,255,0,255]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #21: should be 0,255,0,255\nat (0, 0) expected: 0,255,0,255 was 255,0,0,255]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #33: should be 0,255,0,255\nat (0, 0) expected: 0,255,0,255 was 255,0,0,255]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #0: should be 0,255,0,255\nat (0, 0) expected: 0,255,0,255 was 255,0,0,255]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #30: should be 0,255,0,255\nat (0, 0) expected: 0,255,0,255 was 255,0,0,255]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #22: should be 255,0,0,255\nat (0, 128) expected: 255,0,0,255 was 0,255,0,255]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #39: should be 0,255,0,255\nat (0, 0) expected: 0,255,0,255 was 255,0,0,255]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #28: should be 255,0,0,255\nat (0, 129) expected: 255,0,0,255 was 0,255,0,255]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #7: should be 255,0,0,255\nat (0, 8) expected: 255,0,0,255 was 0,255,0,255]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #36: should be 0,255,0,255\nat (0, 0) expected: 0,255,0,255 was 255,0,0,255]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #42: should be 0,255,0,255\nat (0, 0) expected: 0,255,0,255 was 255,0,0,255]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #27: should be 0,255,0,255\nat (0, 0) expected: 0,255,0,255 was 255,0,0,255]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #13: should be 255,0,0,255\nat (0, 9) expected: 255,0,0,255 was 0,255,0,255]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #37: should be 255,0,0,255\nat (0, 256) expected: 255,0,0,255 was 0,255,0,255]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #6: should be 0,255,0,255\nat (0, 0) expected: 0,255,0,255 was 255,0,0,255]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
[readPixelsBadArgs.html]
|
|
||||||
bug: https://github.com/servo/servo/issues/21522
|
|
||||||
[WebGL test #1: testReadPixelsSOPIMG]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[WebGL test #2: testReadPixelsSOPCanvas]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
[texImage2DHTML.html]
|
|
||||||
bug: https://github.com/servo/servo/issues/21522
|
|
||||||
[WebGL test #1: testTexImage2DNonSOP]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
[texSubImage2DHTML.html]
|
|
||||||
bug: https://github.com/servo/servo/issues/21522
|
|
||||||
[WebGL test #1: testTexImage2DNonSOP]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
[origin-clean-conformance.html]
|
|
||||||
[WebGL test #3: texSubImage2D with cross-origin image should throw exception.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[WebGL test #8: texSubImage2D with NON origin clean canvas should throw exception.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[WebGL test #2: texImage2D with cross-origin image should throw exception.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[WebGL test #7: texImage2D with NON origin clean canvas should throw exception.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue