mirror of
https://github.com/scratchfoundation/scratch-vm.git
synced 2025-01-10 15:02:06 -05:00
Fix issue where non-strings were getting passed in to escape functions for handling special characters that can appear in xml. Add tests.
This commit is contained in:
parent
765f2b2549
commit
c761a9c82e
4 changed files with 88 additions and 2 deletions
|
@ -1,3 +1,5 @@
|
||||||
|
const log = require('./log');
|
||||||
|
|
||||||
class StringUtil {
|
class StringUtil {
|
||||||
static withoutTrailingDigits (s) {
|
static withoutTrailingDigits (s) {
|
||||||
let i = s.length - 1;
|
let i = s.length - 1;
|
||||||
|
@ -62,10 +64,21 @@ class StringUtil {
|
||||||
* in cases where we're replacing non-user facing strings (e.g. variable IDs).
|
* in cases where we're replacing non-user facing strings (e.g. variable IDs).
|
||||||
* When replacing user facing strings, the xmlEscape utility function should be used
|
* When replacing user facing strings, the xmlEscape utility function should be used
|
||||||
* instead so that the user facing string does not change how it displays.
|
* instead so that the user facing string does not change how it displays.
|
||||||
* @param {!string} unsafe Unsafe string possibly containing unicode control characters.
|
* @param {!string | !Array.<string>} unsafe Unsafe string possibly containing unicode control characters.
|
||||||
|
* In some cases this argument may be an array (e.g. hacked inputs from 2.0)
|
||||||
* @return {string} String with control characters replaced.
|
* @return {string} String with control characters replaced.
|
||||||
*/
|
*/
|
||||||
static replaceUnsafeChars (unsafe) {
|
static replaceUnsafeChars (unsafe) {
|
||||||
|
if (typeof unsafe !== 'string') {
|
||||||
|
if (Array.isArray(unsafe)) {
|
||||||
|
// This happens when we have hacked blocks from 2.0
|
||||||
|
// See #1030
|
||||||
|
unsafe = String(unsafe);
|
||||||
|
} else {
|
||||||
|
log.error('Unexpected input recieved in replaceUnsafeChars');
|
||||||
|
return unsafe;
|
||||||
|
}
|
||||||
|
}
|
||||||
return unsafe.replace(/[<>&'"]/g, c => {
|
return unsafe.replace(/[<>&'"]/g, c => {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case '<': return 'lt';
|
case '<': return 'lt';
|
||||||
|
|
|
@ -1,12 +1,24 @@
|
||||||
|
const log = require('./log');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Escape a string to be safe to use in XML content.
|
* Escape a string to be safe to use in XML content.
|
||||||
* CC-BY-SA: hgoebl
|
* CC-BY-SA: hgoebl
|
||||||
* https://stackoverflow.com/questions/7918868/
|
* https://stackoverflow.com/questions/7918868/
|
||||||
* how-to-escape-xml-entities-in-javascript
|
* how-to-escape-xml-entities-in-javascript
|
||||||
* @param {!string} unsafe Unsafe string.
|
* @param {!string | !Array.<string>} unsafe Unsafe string.
|
||||||
* @return {string} XML-escaped string, for use within an XML tag.
|
* @return {string} XML-escaped string, for use within an XML tag.
|
||||||
*/
|
*/
|
||||||
const xmlEscape = function (unsafe) {
|
const xmlEscape = function (unsafe) {
|
||||||
|
if (typeof unsafe !== 'string') {
|
||||||
|
if (Array.isArray(unsafe)) {
|
||||||
|
// This happens when we have hacked blocks from 2.0
|
||||||
|
// See #1030
|
||||||
|
unsafe = String(unsafe);
|
||||||
|
} else {
|
||||||
|
log.error('Unexpected input recieved in replaceUnsafeChars');
|
||||||
|
return unsafe;
|
||||||
|
}
|
||||||
|
}
|
||||||
return unsafe.replace(/[<>&'"]/g, c => {
|
return unsafe.replace(/[<>&'"]/g, c => {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case '<': return '<';
|
case '<': return '<';
|
||||||
|
|
|
@ -109,3 +109,21 @@ test('replaceUnsafeChars', t => {
|
||||||
|
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('replaceUnsafeChars should handle non strings', t => {
|
||||||
|
const array = ['hello', 'world'];
|
||||||
|
t.equal(StringUtil.replaceUnsafeChars(array), String(array));
|
||||||
|
|
||||||
|
const arrayWithSpecialChar = ['hello', '<world>'];
|
||||||
|
t.equal(StringUtil.replaceUnsafeChars(arrayWithSpecialChar), 'hello,ltworldgt');
|
||||||
|
|
||||||
|
const arrayWithNumbers = [1, 2, 3];
|
||||||
|
t.equal(StringUtil.replaceUnsafeChars(arrayWithNumbers), '1,2,3');
|
||||||
|
|
||||||
|
// Objects shouldn't get provided to replaceUnsafeChars, but in the event
|
||||||
|
// they do, it should just return the object (and log an error)
|
||||||
|
const object = {hello: 'world'};
|
||||||
|
t.equal(StringUtil.replaceUnsafeChars(object), object);
|
||||||
|
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
|
|
@ -7,3 +7,46 @@ test('escape', t => {
|
||||||
t.strictEqual(xml(input), output);
|
t.strictEqual(xml(input), output);
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('xmlEscape (more)', t => {
|
||||||
|
const empty = '';
|
||||||
|
t.equal(xml(empty), empty);
|
||||||
|
|
||||||
|
const safe = 'hello';
|
||||||
|
t.equal(xml(safe), safe);
|
||||||
|
|
||||||
|
const unsafe = '< > & \' "';
|
||||||
|
t.equal(xml(unsafe), '< > & ' "');
|
||||||
|
|
||||||
|
const single = '&';
|
||||||
|
t.equal(xml(single), '&');
|
||||||
|
|
||||||
|
const mix = '<a>b& c\'def_-"';
|
||||||
|
t.equal(xml(mix), '<a>b& c'def_-"');
|
||||||
|
|
||||||
|
const dupes = '<<&_"_"_&>>';
|
||||||
|
t.equal(xml(dupes), '<<&_"_"_&>>');
|
||||||
|
|
||||||
|
const emoji = '(>^_^)>';
|
||||||
|
t.equal(xml(emoji), '(>^_^)>');
|
||||||
|
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('xmlEscape should handle non strings', t => {
|
||||||
|
const array = ['hello', 'world'];
|
||||||
|
t.equal(xml(array), String(array));
|
||||||
|
|
||||||
|
const arrayWithSpecialChar = ['hello', '<world>'];
|
||||||
|
t.equal(xml(arrayWithSpecialChar), 'hello,<world>');
|
||||||
|
|
||||||
|
const arrayWithNumbers = [1, 2, 3];
|
||||||
|
t.equal(xml(arrayWithNumbers), '1,2,3');
|
||||||
|
|
||||||
|
// Objects shouldn't get provided to replaceUnsafeChars, but in the event
|
||||||
|
// they do, it should just return the object (and log an error)
|
||||||
|
const object = {hello: 'world'};
|
||||||
|
t.equal(xml(object), object);
|
||||||
|
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
|
Loading…
Reference in a new issue