From edf3c5eaf772584013cb728855ff124584db2094 Mon Sep 17 00:00:00 2001 From: Barney Carroll Date: Thu, 24 Nov 2016 12:25:00 +0000 Subject: [PATCH 1/3] Tests for contenteditable trust, including failing test for #1421 --- render/tests/test-attributes.js | 58 +++++++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/render/tests/test-attributes.js b/render/tests/test-attributes.js index 6df82eaf..73cbd685 100644 --- a/render/tests/test-attributes.js +++ b/render/tests/test-attributes.js @@ -79,9 +79,9 @@ o.spec("attributes", function() { o.spec("canvas width and height", function() { o("uses attribute API", function() { var canvas = {tag: "canvas", attrs: {width: "100%"}} - + render(root, canvas) - + o(canvas.dom.attributes["width"].nodeValue).equals("100%") o(canvas.dom.width).equals(100) }) @@ -95,4 +95,58 @@ o.spec("attributes", function() { o(a.dom.attributes["class"].nodeValue).equals("test") }) }) + o.spec("contenteditable throws on untrusted children", function() { + o("including text nodes", function() { + var div = {tag: "div", attrs: {contenteditable: true}, text: ''} + var succeeded = false + + try { + render(root, div) + + succeeded = true + } + catch(e){} + + o(succeeded).equals(false) + }) + o("including elements", function() { + var div = {tag: "div", attrs: {contenteditable: true}, children: [{tag: "script", attrs: {src: "http://evil.com"}}]} + var succeeded = false + + try { + render(root, div) + + succeeded = true + } + catch(e){} + + o(succeeded).equals(false) + }) + o("tolerating empty children", function() { + var div = {tag: "div", attrs: {contenteditable: true}, children: []} + var succeeded = false + + try { + render(root, div) + + succeeded = true + } + catch(e){} + + o(succeeded).equals(true) + }) + o("tolerating trusted content", function() { + var div = {tag: "div", attrs: {contenteditable: true}, children: [{tag: "<", children: ""}]} + var succeeded = false + + try { + render(root, div) + + succeeded = true + } + catch(e){} + + o(succeeded).equals(true) + }) + }) }) From e8669ad5c80310299d458a5c12bc82191c8ffa0e Mon Sep 17 00:00:00 2001 From: Barney Carroll Date: Thu, 24 Nov 2016 12:29:45 +0000 Subject: [PATCH 2/3] Fix #1421 --- render/render.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/render/render.js b/render/render.js index 909477a2..c31a79ce 100644 --- a/render/render.js +++ b/render/render.js @@ -135,7 +135,7 @@ module.exports = function($window) { else { var recycling = isRecyclable(old, vnodes) if (recycling) old = old.concat(old.pool) - + var oldStart = 0, start = 0, oldEnd = old.length - 1, end = vnodes.length - 1, map while (oldEnd >= oldStart && end >= start) { var o = old[oldStart], v = vnodes[start] @@ -347,7 +347,7 @@ module.exports = function($window) { var content = children[0].children if (vnode.dom.innerHTML !== content) vnode.dom.innerHTML = content } - else if (children != null || vnode.text != null) throw new Error("Child node of a contenteditable must be trusted") + else if (vnode.text != null || children != null && children.length !== 0) throw new Error("Child node of a contenteditable must be trusted") } //remove From b87cf7b28853aab4cd306afc24d7507b81027c32 Mon Sep 17 00:00:00 2001 From: Gandalf-the-Bot Date: Thu, 24 Nov 2016 13:19:40 +0000 Subject: [PATCH 3/3] Bundled output for commit b4ada9284c47b14de50f2190380507046cbb18e1 [skip ci] --- README.md | 2 +- mithril.js | 3 +- mithril.min.js | 78 +++++++++++++++++++++++++------------------------- 3 files changed, 41 insertions(+), 42 deletions(-) diff --git a/README.md b/README.md index f748cef7..71c22280 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,6 @@ There are over 4000 assertions in the test suite, and tests cover even difficult ## Modularity -Despite the huge improvements in performance and modularity, the new codebase is smaller than v0.2.x, currently clocking at 7.40 KB min+gzip +Despite the huge improvements in performance and modularity, the new codebase is smaller than v0.2.x, currently clocking at 7.41 KB min+gzip In addition, Mithril is now completely modular: you can import only the modules that you need and easily integrate 3rd party modules if you wish to use a different library for routing, ajax, and even rendering diff --git a/mithril.js b/mithril.js index 7fdbec3a..a81fa58e 100644 --- a/mithril.js +++ b/mithril.js @@ -467,7 +467,6 @@ var _13 = function($window) { else { var recycling = isRecyclable(old, vnodes) if (recycling) old = old.concat(old.pool) - var oldStart = 0, start = 0, oldEnd = old.length - 1, end = vnodes.length - 1, map while (oldEnd >= oldStart && end >= start) { var o = old[oldStart], v = vnodes[start] @@ -677,7 +676,7 @@ var _13 = function($window) { var content = children[0].children if (vnode.dom.innerHTML !== content) vnode.dom.innerHTML = content } - else if (children != null || vnode.text != null) throw new Error("Child node of a contenteditable must be trusted") + else if (vnode.text != null || children != null && children.length !== 0) throw new Error("Child node of a contenteditable must be trusted") } //remove function removeNodes(vnodes, start, end, context) { diff --git a/mithril.min.js b/mithril.min.js index 41590c4a..044beb36 100644 --- a/mithril.min.js +++ b/mithril.min.js @@ -1,40 +1,40 @@ -new function(){function m(a,b,k,e,l,h){return{tag:a,key:b,attrs:k,children:e,text:l,dom:h,domSize:void 0,state:{},events:void 0,instance:void 0,skip:!1}}function t(a){if(null==a||"string"!==typeof a&&null==a.view)throw Error("The selector must be either a string or a component.");if("string"===typeof a&&void 0===H[a]){for(var b,k,e=[],l={};b=O.exec(a);){var h=b[1],v=b[2];""===h&&""!==v?k=v:"#"===h?l.id=v:"."===h?e.push(v):"["===b[3][0]&&((h=b[6])&&(h=h.replace(/\\(["'])/g,"$1").replace(/\\\\/g,"\\")), -"class"===b[4]?e.push(h):l[b[4]]=h||!0)}0a.indexOf("?")?"?":"&";a+=e+f}return a}function v(a){try{return""!== -a?JSON.parse(a):null}catch(w){throw Error(a);}}function p(a){return a.responseText}function r(a,b){if("function"===typeof a)if(b instanceof Array)for(var e=0;en.status||304===n.status)b(r(f.type,a));else{var h=Error(n.responseText),k;for(k in a)h[k]=a[k];e(h)}}catch(G){e(G)}}; -u&&null!=f.data?n.send(f.data):n.send()}))},jsonp:function(f){return e(new b(function(b,e){var n=f.callbackName||"_mithril_"+Math.round(1E16*Math.random())+"_"+m++,k=a.document.createElement("script");a[n]=function(e){k.parentNode.removeChild(k);b(r(f.type,e));delete a[n]};k.onerror=function(){k.parentNode.removeChild(k);e(Error("JSONP request failed"));delete a[n]};null==f.data&&(f.data={});f.url=l(f.url,f.data);f.data[f.callbackKey||"callback"]=n;k.src=h(f.url,f.data);a.document.documentElement.appendChild(k)}))}, -setCompletionCallback:function(a){q=a}}}(window,"undefined"!==typeof Promise?Promise:y),J=function(){var a=[];return{subscribe:a.push.bind(a),unsubscribe:function(b){b=a.indexOf(b);-1=A&&B>=l;){var x=a[A],m=d[l];if(x!==m||g)if(null==x)A++;else if(null==m)l++;else if(x.key===m.key)A++,l++,h(c,x,m,f,p(a,A,e),g,n),g&&x.tag===m.tag&&r(c,v(x),e); -else if(x=a[q],x!==m||g)if(null==x)q--;else if(null==m)l++;else if(x.key===m.key)h(c,x,m,f,p(a,q+1,e),g,n),(g||l=A&&B>=l;){x=a[q];m=d[B];if(x!==m||g)if(null==x)q--;else{if(null!=m)if(x.key===m.key)h(c,x,m,f,p(a,q+1,e),g,n),g&&x.tag===m.tag&&r(c,v(x),e),null!=x.dom&&(e=x.dom),q--;else{if(!w){w=a;var x=q,D={},z;for(z=0;za.indexOf("?")?"?":"&";a+=d+g}return a}function v(a){try{return""!== +a?JSON.parse(a):null}catch(w){throw Error(a);}}function p(a){return a.responseText}function r(a,b){if("function"===typeof a)if(b instanceof Array)for(var d=0;dn.status||304===n.status)b(r(g.type,a));else{var h=Error(n.responseText),k;for(k in a)h[k]=a[k];d(h)}}catch(G){d(G)}}; +u&&null!=g.data?n.send(g.data):n.send()}))},jsonp:function(g){return d(new b(function(b,d){var n=g.callbackName||"_mithril_"+Math.round(1E16*Math.random())+"_"+m++,k=a.document.createElement("script");a[n]=function(d){k.parentNode.removeChild(k);b(r(g.type,d));delete a[n]};k.onerror=function(){k.parentNode.removeChild(k);d(Error("JSONP request failed"));delete a[n]};null==g.data&&(g.data={});g.url=l(g.url,g.data);g.data[g.callbackKey||"callback"]=n;k.src=h(g.url,g.data);a.document.documentElement.appendChild(k)}))}, +setCompletionCallback:function(a){q=a}}}(window,"undefined"!==typeof Promise?Promise:y),J=function(){var a=[];return{subscribe:a.push.bind(a),unsubscribe:function(b){b=a.indexOf(b);-1=A&&B>=l;){var x=a[A],m=e[l];if(x!==m||f)if(null==x)A++;else if(null==m)l++;else if(x.key===m.key)A++,l++,h(c,x,m,g,p(a,A,d),f,n),f&&x.tag===m.tag&&r(c,v(x),d); +else if(x=a[q],x!==m||f)if(null==x)q--;else if(null==m)l++;else if(x.key===m.key)h(c,x,m,g,p(a,q+1,d),f,n),(f||l=A&&B>=l;){x=a[q];m=e[B];if(x!==m||f)if(null==x)q--;else{if(null!=m)if(x.key===m.key)h(c,x,m,g,p(a,q+1,d),f,n),f&&x.tag===m.tag&&r(c,v(x),d),null!=x.dom&&(d=x.dom),q--;else{if(!w){w=a;var x=q,D={},z;for(z=0;z