mirror of
https://github.com/scratchfoundation/scratch-vm.git
synced 2024-12-22 14:02:37 -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 {
|
||||
static withoutTrailingDigits (s) {
|
||||
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).
|
||||
* 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.
|
||||
* @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.
|
||||
*/
|
||||
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 => {
|
||||
switch (c) {
|
||||
case '<': return 'lt';
|
||||
|
|
|
@ -1,12 +1,24 @@
|
|||
const log = require('./log');
|
||||
|
||||
/**
|
||||
* Escape a string to be safe to use in XML content.
|
||||
* CC-BY-SA: hgoebl
|
||||
* https://stackoverflow.com/questions/7918868/
|
||||
* 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.
|
||||
*/
|
||||
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 => {
|
||||
switch (c) {
|
||||
case '<': return '<';
|
||||
|
|
|
@ -109,3 +109,21 @@ test('replaceUnsafeChars', t => {
|
|||
|
||||
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.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