From f73ef510384380441c7535b64996cafb58918b0b Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Mon, 25 Feb 2019 17:02:30 -0500 Subject: [PATCH] fix(parse): remove backspace control characters from input to be parsed --- lib/parse.js | 8 +- ...har_in_strings_credit_to_Mr-Dave_test.json | 96 +++++++++++++++++++ ...har_in_strings_credit_to_Mr-Dave_test.json | 1 + test/unit/parser.js | 37 +++++++ 4 files changed, 141 insertions(+), 1 deletion(-) create mode 100755 test/fixtures/data/217845144_sb2_control_char_in_strings_credit_to_Mr-Dave_test.json create mode 100755 test/fixtures/data/217845144_sb3_control_char_in_strings_credit_to_Mr-Dave_test.json diff --git a/lib/parse.js b/lib/parse.js index db0ce271..d0557407 100644 --- a/lib/parse.js +++ b/lib/parse.js @@ -10,7 +10,13 @@ module.exports = function (input, callback) { var result; try { - result = JSON.parse(input); + // The input is a JSON string, which may contain control characters + // that should be removed. See LLK/scratch-vm#1077 + // So far we've only encountered the backspace control character, + // so remove that specific one before continuing. + // SB2 JSONs and SB3 JSONs have different versions of the + // character serialized (e.g. \u0008 and \b), strip out both versions + result = JSON.parse(input.replace(/\\b|\\u0008/g, '')); } catch (e) { return callback(e.toString()); } diff --git a/test/fixtures/data/217845144_sb2_control_char_in_strings_credit_to_Mr-Dave_test.json b/test/fixtures/data/217845144_sb2_control_char_in_strings_credit_to_Mr-Dave_test.json new file mode 100755 index 00000000..5319bf53 --- /dev/null +++ b/test/fixtures/data/217845144_sb2_control_char_in_strings_credit_to_Mr-Dave_test.json @@ -0,0 +1,96 @@ +{ + "objName": "Stage", + "variables": [{ + "name": "\u0008b-damage", + "value": 47.600000000000406, + "isPersistent": false + }], + "sounds": [{ + "soundName": "pop", + "soundID": 1, + "md5": "83a9787d4cb6f3b7632b4ddfebf74367.wav", + "sampleCount": 258, + "rate": 11025, + "format": "" + }], + "costumes": [{ + "costumeName": "backdrop1", + "baseLayerID": 3, + "baseLayerMD5": "739b5e2a2435f6e1ec2993791b423146.png", + "bitmapResolution": 1, + "rotationCenterX": 240, + "rotationCenterY": 180 + }], + "currentCostumeIndex": 0, + "penLayerMD5": "5c81a336fab8be57adc039a8a2b33ca9.png", + "penLayerID": 0, + "tempoBPM": 60, + "videoAlpha": 0.5, + "children": [{ + "objName": "Sprite1", + "scripts": [[178.4, + 46.15, + [["whenGreenFlag"], + ["setVar:to:", "\u0008b-damage", "2"], + ["doForever", [["turnRight:", ["readVariable", "\u0008b-damage"]], ["changeVar:by:", "\u0008b-damage", 0.1]]]]]], + "sounds": [{ + "soundName": "meow", + "soundID": 0, + "md5": "83c36d806dc92327b9e7049a565c6bff.wav", + "sampleCount": 18688, + "rate": 22050, + "format": "" + }], + "costumes": [{ + "costumeName": "costume1", + "baseLayerID": 1, + "baseLayerMD5": "09dc888b0b7df19f70d81588ae73420e.svg", + "bitmapResolution": 1, + "rotationCenterX": 47, + "rotationCenterY": 55 + }, + { + "costumeName": "costume2", + "baseLayerID": 2, + "baseLayerMD5": "3696356a03a8d938318876a593572843.svg", + "bitmapResolution": 1, + "rotationCenterX": 47, + "rotationCenterY": 55 + }], + "currentCostumeIndex": 0, + "scratchX": -12.550000000000011, + "scratchY": -22, + "scale": 1, + "direction": 105.79999999757408, + "rotationStyle": "normal", + "isDraggable": false, + "indexInLibrary": 1, + "visible": true, + "spriteInfo": { + } + }, + { + "target": "Stage", + "cmd": "getVar:", + "param": "\u0008b-damage", + "color": 15629590, + "label": "\u0008b-damage", + "mode": 1, + "sliderMin": 0, + "sliderMax": 100, + "isDiscrete": true, + "x": 5, + "y": 5, + "visible": true + }], + "info": { + "userAgent": "Mozilla\/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/68.0.3440.106 Safari\/537.36", + "swfVersion": "v461", + "spriteCount": 1, + "videoOn": false, + "hasCloudData": false, + "scriptCount": 1, + "flashVersion": "MAC 31,0,0,108", + "projectID": "217845144" + } +} diff --git a/test/fixtures/data/217845144_sb3_control_char_in_strings_credit_to_Mr-Dave_test.json b/test/fixtures/data/217845144_sb3_control_char_in_strings_credit_to_Mr-Dave_test.json new file mode 100755 index 00000000..e05e05b6 --- /dev/null +++ b/test/fixtures/data/217845144_sb3_control_char_in_strings_credit_to_Mr-Dave_test.json @@ -0,0 +1 @@ +{"targets":[{"isStage":true,"name":"Stage","variables":{"|fg9Sax{3^M|yQ/@+Pb^-\bb-damage-":["\bb-damage",47.600000000000406]},"lists":{},"broadcasts":{},"blocks":{},"comments":{},"currentCostume":0,"costumes":[{"assetId":"797b03bdb8cf6ccfc30c0692d533d998","name":"backdrop1","bitmapResolution":2,"md5ext":"797b03bdb8cf6ccfc30c0692d533d998.png","dataFormat":"png","rotationCenterX":480,"rotationCenterY":360}],"sounds":[{"assetId":"83a9787d4cb6f3b7632b4ddfebf74367","name":"pop","dataFormat":"wav","format":"","rate":44100,"sampleCount":1032,"md5ext":"83a9787d4cb6f3b7632b4ddfebf74367.wav"}],"volume":100,"layerOrder":0,"tempo":60,"videoTransparency":50,"videoState":"off","textToSpeechLanguage":null},{"isStage":false,"name":"Sprite1","variables":{},"lists":{},"broadcasts":{},"blocks":{"Fo3;}RZh889lf|v)*Wc8":{"opcode":"event_whenflagclicked","next":"s.no,^PDr@)KV@#Z([zR","parent":null,"inputs":{},"fields":{},"shadow":false,"topLevel":true,"x":268,"y":102},"s.no,^PDr@)KV@#Z([zR":{"opcode":"data_setvariableto","next":"s7Tv-QPZwL]v-?_)4Cec","parent":"Fo3;}RZh889lf|v)*Wc8","inputs":{"VALUE":[1,[10,"2"]]},"fields":{"VARIABLE":["\bb-damage","|fg9Sax{3^M|yQ/@+Pb^-\bb-damage-"]},"shadow":false,"topLevel":false},"s7Tv-QPZwL]v-?_)4Cec":{"opcode":"control_forever","next":null,"parent":"s.no,^PDr@)KV@#Z([zR","inputs":{"SUBSTACK":[2,"7/?b1TW-/8UT)P}LqB|t"]},"fields":{},"shadow":false,"topLevel":false},"7/?b1TW-/8UT)P}LqB|t":{"opcode":"motion_turnright","next":"phnMvNrC#eBgG0L!TxRq","parent":"s7Tv-QPZwL]v-?_)4Cec","inputs":{"DEGREES":[3,[12,"\bb-damage","|fg9Sax{3^M|yQ/@+Pb^-\bb-damage-"],[4,10]]},"fields":{},"shadow":false,"topLevel":false},"phnMvNrC#eBgG0L!TxRq":{"opcode":"data_changevariableby","next":null,"parent":"7/?b1TW-/8UT)P}LqB|t","inputs":{"VALUE":[1,[4,0.1]]},"fields":{"VARIABLE":["\bb-damage","|fg9Sax{3^M|yQ/@+Pb^-\bb-damage-"]},"shadow":false,"topLevel":false}},"comments":{},"currentCostume":0,"costumes":[{"assetId":"bcaaa8547a07cfe572c0967ba829e99d","name":"costume1","bitmapResolution":1,"md5ext":"bcaaa8547a07cfe572c0967ba829e99d.svg","dataFormat":"svg","rotationCenterX":47,"rotationCenterY":55},{"assetId":"11d6c5fbd91e433a1b85a00fd9dd43b6","name":"costume2","bitmapResolution":1,"md5ext":"11d6c5fbd91e433a1b85a00fd9dd43b6.svg","dataFormat":"svg","rotationCenterX":47,"rotationCenterY":55}],"sounds":[{"assetId":"83c36d806dc92327b9e7049a565c6bff","name":"meow","dataFormat":"wav","format":"","rate":44100,"sampleCount":37376,"md5ext":"83c36d806dc92327b9e7049a565c6bff.wav"}],"volume":100,"layerOrder":1,"visible":true,"x":-12.550000000000011,"y":-22,"size":100,"direction":105.79999999757408,"draggable":false,"rotationStyle":"all around"}],"monitors":[{"id":"|fg9Sax{3^M|yQ/@+Pb^-\bb-damage-","mode":"default","opcode":"data_variable","params":{"VARIABLE":"\bb-damage"},"spriteName":null,"value":47.600000000000406,"x":5,"y":5,"visible":true,"sliderMin":0,"sliderMax":100,"isDiscrete":true}],"extensions":[],"meta":{"semver":"3.0.0","vm":"0.2.0-prerelease.20190213190040","agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36"}} \ No newline at end of file diff --git a/test/unit/parser.js b/test/unit/parser.js index d07eeab9..3f6cbed3 100644 --- a/test/unit/parser.js +++ b/test/unit/parser.js @@ -1,3 +1,5 @@ +var fs = require('fs'); +var path = require('path'); var test = require('tap').test; var parse = require('../../lib/parse'); var data = require('../fixtures/data'); @@ -24,3 +26,38 @@ test('invalid', function (t) { t.end(); }); }); + +test('backspace control characters get stripped out in sb2', function (t) { + var backspaceControlSb2 = fs.readFileSync( + path.resolve(__dirname, '../fixtures/data/217845144_sb2_control_char_in_strings_credit_to_Mr-Dave_test.json')); + parse(backspaceControlSb2.toString(), function (err, res) { + t.equal(err, null); + t.type(res, 'object'); + + // Verify that the object doesn't have a control character in the global variable name + t.equal(Array.isArray(res.variables), true); + t.equal(res.variables.length, 1); + // The parsed string should no longer include a backspace control character + t.equal(res.variables[0].name, 'b-damage'); + t.end(); + }); +}); + +test('backspace control characters get stripped out in sb3', function (t) { + var backspaceControlSb2 = fs.readFileSync( + path.resolve(__dirname, '../fixtures/data/217845144_sb3_control_char_in_strings_credit_to_Mr-Dave_test.json')); + parse(backspaceControlSb2.toString(), function (err, res) { + t.equal(err, null); + t.type(res, 'object'); + + // Verify that the object doesn't have a control character in the global variable name + t.equal(Array.isArray(res.targets), true); + t.equal(res.targets.length, 2); + t.type(res.targets[0].variables, 'object'); + var backspaceControlVariableId = Object.keys(res.targets[0].variables)[0]; + var backspaceControlVariable = res.targets[0].variables[backspaceControlVariableId]; + // The parsed string should no longer include a backspace control character + t.equal(backspaceControlVariable[0], 'b-damage'); + t.end(); + }); +});