Upstream microcosm-cc/bluemonday state of the touched files before 3b7d7c9bed
This commit is contained in:
1 parent
2ad537dcd8
commit
11fba4f573
2 files changed
+3
-108
No files matched your search
+3
-19
@@ -337,32 +337,16 @@ func multiSplit(value string, seps ...string) []string {
|
|||||||
return curArray
|
return curArray
|
||||||
}
|
}
|
||||||
|
|
||||||
// recursiveCheck reports whether value can be split, in order, into groups
|
|
||||||
// of tokens each accepted by one of funcs. The outcome depends only on how
|
|
||||||
// many tokens remain, so memoizing on that length keeps the search
|
|
||||||
// polynomial without changing which values are accepted.
|
|
||||||
func recursiveCheck(value []string, funcs []func(string) bool) bool {
|
func recursiveCheck(value []string, funcs []func(string) bool) bool {
|
||||||
memo := make(map[int]bool, len(value))
|
|
||||||
return recursiveCheckMemo(value, funcs, memo)
|
|
||||||
}
|
|
||||||
|
|
||||||
func recursiveCheckMemo(value []string, funcs []func(string) bool, memo map[int]bool) bool {
|
|
||||||
if cached, ok := memo[len(value)]; ok {
|
|
||||||
return cached
|
|
||||||
}
|
|
||||||
result := false
|
|
||||||
outer:
|
|
||||||
for i := 0; i < len(value); i++ {
|
for i := 0; i < len(value); i++ {
|
||||||
tempVal := strings.Join(value[:i+1], " ")
|
tempVal := strings.Join(value[:i+1], " ")
|
||||||
for _, j := range funcs {
|
for _, j := range funcs {
|
||||||
if j(tempVal) && (len(value[i+1:]) == 0 || recursiveCheckMemo(value[i+1:], funcs, memo)) {
|
if j(tempVal) && (len(value[i+1:]) == 0 || recursiveCheck(value[i+1:], funcs)) {
|
||||||
result = true
|
return true
|
||||||
break outer
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
memo[len(value)] = result
|
return false
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func in(value []string, arr []string) bool {
|
func in(value []string, arr []string) bool {
|
||||||
|
|||||||
@@ -1,89 +0,0 @@
|
|||||||
// Copyright (c) 2019, David Kitchen <david@buro9.com>
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright notice, this
|
|
||||||
// list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
// this list of conditions and the following disclaimer in the documentation
|
|
||||||
// and/or other materials provided with the distribution.
|
|
||||||
//
|
|
||||||
// * Neither the name of the organisation (Microcosm) nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
||||||
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
package css
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Regression test for https://github.com/microcosm-cc/bluemonday/issues/225.
|
|
||||||
// Whitespace-only tokens give recursiveCheck many equally valid split points;
|
|
||||||
// unmemoized it re-explored each one, taking ~4s for the value below. The
|
|
||||||
// verdict is unchanged (rejected either way), only the time to reach it.
|
|
||||||
func TestIssue225(t *testing.T) {
|
|
||||||
// 20 blank tokens, as the issue #225 payload produced them.
|
|
||||||
pathological := "normal\n" + strings.Repeat(" ", 20) + "16px\nroboto"
|
|
||||||
|
|
||||||
const deadline = 3 * time.Second
|
|
||||||
const want = false
|
|
||||||
|
|
||||||
result := make(chan bool, 1)
|
|
||||||
go func() {
|
|
||||||
result <- FontHandler(pathological)
|
|
||||||
}()
|
|
||||||
|
|
||||||
select {
|
|
||||||
case got := <-result:
|
|
||||||
if got != want {
|
|
||||||
t.Errorf("FontHandler(%q) = %v, want %v", pathological, got, want)
|
|
||||||
}
|
|
||||||
case <-time.After(deadline):
|
|
||||||
t.Fatalf("FontHandler did not return within %v for a 20-blank-token "+
|
|
||||||
"value; recursiveCheck may have regressed to exponential-time "+
|
|
||||||
"behaviour (see issue #225)", deadline)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Memoization must not change which values FontHandler accepts, only how
|
|
||||||
// fast it decides. Expectations captured from the pre-fix behaviour.
|
|
||||||
func TestIssue225AcceptanceUnchanged(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
value string
|
|
||||||
want bool
|
|
||||||
}{
|
|
||||||
// Valid "font" shorthand values.
|
|
||||||
{"italic bold 12px/30px Georgia, serif", true},
|
|
||||||
{"icon", true},
|
|
||||||
{"caption", true},
|
|
||||||
{"normal 16px Roboto", true},
|
|
||||||
{"bold 16px/1.5 Arial, sans-serif", true},
|
|
||||||
// Invalid/unsafe values that must stay rejected.
|
|
||||||
{"expression(alert(1))", false},
|
|
||||||
{"javascript:alert(1)", false},
|
|
||||||
{"url(evil.com)", false},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
if got := FontHandler(tt.value); got != tt.want {
|
|
||||||
t.Errorf("FontHandler(%q) = %v, want %v", tt.value, got, tt.want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in new issue
Block a user