Skip to content

Commit e5c6f33

Browse files
wangw-1991chromium-wpt-export-bot
authored andcommitted
[WebNN] Reject conv2d/pool2d/convTranspose2d strides, dilations and
filters that exceed the usable extent conv2d, pooling and convTranspose2d take strides and dilations as unsigned long and the only validation was a != 0 check on each value. When the input spatial size and the filter/window are 1x1, the derived output size collapses to 1 for any stride/dilation, so an arbitrarily large value survives all output-size math and is serialized verbatim into the backend graph, even though it is semantically equivalent to a much smaller value and cannot legitimately arise. This CL adds an upper bound in the output-size validation: - Forward conv2d and pool2d: reject a stride or dilation larger than the padded input spatial size. Padding is included so that valid padded windows are not rejected. A value larger than the padded input can place the window at most once, so it is always equivalent to a smaller value. - Forward conv2d and pool2d: reject an effective (dilated) filter window larger than the padded input spatial size. when the effective filter size exceeds the padded input, the window can never be fully placed, so the operation has no valid output. - ConvTranspose2d: a stride or dilation larger than the output size can only arise when input==1 or filter==1, where its value is a pure no-op. Reject such values so that unbounded uint32 strides/dilations can not flow unchecked into backends This CL also adds WPTs for the new checks. There is a related discussion about this in the spec issue[1]. [1] webmachinelearning/webnn#928 (comment) Fixed: 546106051 Change-Id: I37eea4793cbd42d2e80aab23e68c127ff0f5381d Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8250961 Reviewed-by: Reilly Grant <reillyg@chromium.org> Reviewed-by: Phillis Tang <phillis@chromium.org> Reviewed-by: Hu, Ningxin <ningxin.hu@intel.com> Commit-Queue: Wang, Wei4 <wei4.wang@intel.com> Cr-Commit-Position: refs/heads/main@{#1682769}
1 parent 389fb4a commit e5c6f33

3 files changed

Lines changed: 161 additions & 0 deletions

File tree

webnn/validation_tests/conv2d.https.any.js

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,67 @@ const tests = [
549549
label: label,
550550
},
551551
},
552+
{
553+
name: '[conv2d] Throw if a stride is larger than the padded input height.',
554+
input: {dataType: 'float32', shape: [1, 1, 5, 5]},
555+
filter: {dataType: 'float32', shape: [1, 1, 1, 1]},
556+
options: {
557+
strides: [kMaxUnsignedLong, 1],
558+
label: label,
559+
},
560+
},
561+
{
562+
name: '[conv2d] Throw if a stride is larger than the padded input width.',
563+
input: {dataType: 'float32', shape: [1, 1, 5, 5]},
564+
filter: {dataType: 'float32', shape: [1, 1, 1, 1]},
565+
options: {
566+
strides: [1, kMaxUnsignedLong],
567+
label: label,
568+
},
569+
},
570+
{
571+
name:
572+
'[conv2d] Throw if a dilation is larger than the padded input height.',
573+
input: {dataType: 'float32', shape: [1, 1, 5, 5]},
574+
filter: {dataType: 'float32', shape: [1, 1, 1, 1]},
575+
options: {
576+
dilations: [kMaxUnsignedLong, 1],
577+
label: label,
578+
},
579+
},
580+
{
581+
name: '[conv2d] Throw if a dilation is larger than the padded input width.',
582+
input: {dataType: 'float32', shape: [1, 1, 5, 5]},
583+
filter: {dataType: 'float32', shape: [1, 1, 1, 1]},
584+
options: {
585+
dilations: [1, kMaxUnsignedLong],
586+
label: label,
587+
},
588+
},
589+
{
590+
name: '[conv2d] Throw if the dilated effective filter height is larger ' +
591+
'than the padded input height.',
592+
input: {dataType: 'float32', shape: [1, 1, 5, 5]},
593+
filter: {dataType: 'float32', shape: [1, 1, 3, 1]},
594+
// Effective filter height = (3 - 1) * 3 + 1 = 7 > padded height 5, while
595+
// the dilation itself (3) is not larger than the padded input.
596+
options: {
597+
dilations: [3, 1],
598+
label: label,
599+
},
600+
},
601+
{
602+
name: '[conv2d] Throw if the dilated effective filter width is larger ' +
603+
'than the padded input width.',
604+
input: {dataType: 'float32', shape: [1, 1, 5, 5]},
605+
filter: {dataType: 'float32', shape: [1, 1, 1, 3]},
606+
// Effective filter width = (3 - 1) * 3 + 1 = 7 > padded width 5, while the
607+
// dilation itself (3) is not larger than the padded input.
608+
options: {
609+
dilations: [1, 3],
610+
label: label,
611+
},
612+
},
552613
];
553614

554615
tests.forEach(

webnn/validation_tests/convTranspose2d.https.any.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,46 @@ const tests = [
549549
label: label,
550550
},
551551
},
552+
{
553+
name:
554+
'[convTranspose2d] Throw if a stride is larger than the output height.',
555+
input: {dataType: 'float32', shape: [1, 1, 1, 1]},
556+
filter: {dataType: 'float32', shape: [1, 1, 1, 1]},
557+
options: {
558+
strides: [kMaxUnsignedLong, 1],
559+
label: label,
560+
},
561+
},
562+
{
563+
name:
564+
'[convTranspose2d] Throw if a stride is larger than the output width.',
565+
input: {dataType: 'float32', shape: [1, 1, 1, 1]},
566+
filter: {dataType: 'float32', shape: [1, 1, 1, 1]},
567+
options: {
568+
strides: [1, kMaxUnsignedLong],
569+
label: label,
570+
},
571+
},
572+
{
573+
name:
574+
'[convTranspose2d] Throw if a dilation is larger than the output height.',
575+
input: {dataType: 'float32', shape: [1, 1, 3, 3]},
576+
filter: {dataType: 'float32', shape: [1, 1, 1, 1]},
577+
options: {
578+
dilations: [kMaxUnsignedLong, 1],
579+
label: label,
580+
},
581+
},
582+
{
583+
name:
584+
'[convTranspose2d] Throw if a dilation is larger than the output width.',
585+
input: {dataType: 'float32', shape: [1, 1, 3, 3]},
586+
filter: {dataType: 'float32', shape: [1, 1, 1, 1]},
587+
options: {
588+
dilations: [1, kMaxUnsignedLong],
589+
label: label,
590+
},
591+
},
552592
];
553593

554594
tests.forEach(

webnn/validation_tests/pooling.https.any.js

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,66 @@ const tests = [
307307
label: label,
308308
},
309309
},
310+
{
311+
name: 'Throw if a stride is larger than the padded input height.',
312+
input: {dataType: 'float32', shape: [1, 3, 5, 5]},
313+
options: {
314+
windowDimensions: [1, 1],
315+
strides: [kMaxUnsignedLong, 1],
316+
label: label,
317+
},
318+
},
319+
{
320+
name: 'Throw if a stride is larger than the padded input width.',
321+
input: {dataType: 'float32', shape: [1, 3, 5, 5]},
322+
options: {
323+
windowDimensions: [1, 1],
324+
strides: [1, kMaxUnsignedLong],
325+
label: label,
326+
},
327+
},
328+
{
329+
name: 'Throw if a dilation is larger than the padded input height.',
330+
input: {dataType: 'float32', shape: [1, 3, 5, 5]},
331+
options: {
332+
windowDimensions: [1, 1],
333+
dilations: [kMaxUnsignedLong, 1],
334+
label: label,
335+
},
336+
},
337+
{
338+
name: 'Throw if a dilation is larger than the padded input width.',
339+
input: {dataType: 'float32', shape: [1, 3, 5, 5]},
340+
options: {
341+
windowDimensions: [1, 1],
342+
dilations: [1, kMaxUnsignedLong],
343+
label: label,
344+
},
345+
},
346+
{
347+
name: 'Throw if the dilated effective window height is larger than the ' +
348+
'padded input height.',
349+
input: {dataType: 'float32', shape: [1, 3, 5, 5]},
350+
// Effective window height = (3 - 1) * 3 + 1 = 7 > padded height 5, while
351+
// the dilation itself (3) is not larger than the padded input.
352+
options: {
353+
windowDimensions: [3, 1],
354+
dilations: [3, 1],
355+
label: label,
356+
},
357+
},
358+
{
359+
name: 'Throw if the dilated effective window width is larger than the ' +
360+
'padded input width.',
361+
input: {dataType: 'float32', shape: [1, 3, 5, 5]},
362+
// Effective window width = (3 - 1) * 3 + 1 = 7 > padded width 5, while the
363+
// dilation itself (3) is not larger than the padded input.
364+
options: {
365+
windowDimensions: [1, 3],
366+
dilations: [1, 3],
367+
label: label,
368+
},
369+
},
310370
];
311371

312372
tests.forEach(

0 commit comments

Comments
 (0)