diff --git a/docs/labs/argument-injection.js b/docs/labs/argument-injection.js index 15e2a45b..4d5e1f21 100644 --- a/docs/labs/argument-injection.js +++ b/docs/labs/argument-injection.js @@ -70,7 +70,7 @@ info = { present: String.raw`\) \) =>`, text: "The `exec` function should be closed in later lines, not here." - } + }, ], expected: [ `execFile('git', ['blame', '--', filePath], { shell: false }, (error, stdout, stderr) => {` @@ -89,7 +89,7 @@ info = " execFile('git', ['blame', '--', filePath], { shell: false }, (error, stdout, stderr) => {", " execFile('git', ['blame', '--', filePath], (error, stdout, stderr) => {", " execFile('git', ['blame', '--', filePath], {}, (error, stdout, stderr) => {" - ] + ], ], failures: [ [ @@ -100,6 +100,6 @@ info = ], [ " execFile('git blame', [filePath], { shell: false }, (error, stdout, stderr) => {" - ] - ] -} + ], + ], +}; diff --git a/docs/labs/assert.js b/docs/labs/assert.js index 98851ae0..1aa6e438 100644 --- a/docs/labs/assert.js +++ b/docs/labs/assert.js @@ -6,14 +6,14 @@ info = text: "The whole point of this exercise is to NOT use `assert` as a way to validate input from untrusted users.", examples: [ [ "assert !bindingResult.hasErrors();\n" ] - ] + ], }, { absent: String.raw`^\s* if `, text: "Begin with `if` so you can return a result if there are errors.", examples: [ [ "return \"form\";" ] - ] + ], }, { present: "(bindingresult|BindingResult)", @@ -28,14 +28,14 @@ info = text: "In Java, after the keyword `if` you must have an open left parenthesis. Conventionally there is one space between the `if` keyword and the open left parenthesis.", examples: [ [ "if bindingResult.hasErrors" ] - ] + ], }, { present: String.raw`^\s*if\s*\(\s*\!binding`, text: "You have an extraneous `!` (not operator). Use the expression if (bindingResult.hasErrors()) ...", examples: [ [ "if (!bindingResult.hasErrors())" ] - ] + ], }, { absent: String.raw`^ if \( bindingResult \. hasErrors \( \) \) `, @@ -79,5 +79,5 @@ info = [ "if ( ! bindingResult . hasErrors ( ) ) { return \"form\" ; }\n" ], [ "if bindingResult . hasErrors ( ) { return \"form\" ; }\n" ], [ "if ( bindingResult . hasErrors ) { return \"form\" ; }\n" ], - ] -} + ], +}; diff --git a/docs/labs/commaize b/docs/labs/commaize new file mode 100755 index 00000000..b8795215 --- /dev/null +++ b/docs/labs/commaize @@ -0,0 +1,21 @@ +#!/bin/sh +# Add trailing commas and terminating semicolon to lab data files + +for file in [a-z]*.js +do + # Skip checker, that has more than data in it. + if [ "$file" == 'checker.js' ]; then + continue + fi + + # Skip anything that isn't a lab data file. + if ! grep -q 'info =' "$file"; then + continue + fi + + htmlfile="${file%.js}.html" + echo "Modifying $file for $htmlfile" + + sed -E -e 's/^( +(\]|\}))$/\1,/' -e '$s/^\}$/};/' "$file" > ,1 + mv ,1 "$file" +done diff --git a/docs/labs/conversion.js b/docs/labs/conversion.js index c290fb93..215e5186 100644 --- a/docs/labs/conversion.js +++ b/docs/labs/conversion.js @@ -8,7 +8,7 @@ info = { present: String.raw`unsigned\s+queue_count`, text: "The declared return type of get_queue is `unsigned int`; you should match it exactly instead of using a synonym like `unsigned`." - } + }, ], expected: [ 'unsigned int queue_count = 0;' @@ -16,4 +16,4 @@ info = correct: [ String.raw`^ unsigned\s+int\s+queue_count = 0 ; $` ], -} +}; diff --git a/docs/labs/create_checker.md b/docs/labs/create_checker.md index b9a99cbf..a344b0e4 100644 --- a/docs/labs/create_checker.md +++ b/docs/labs/create_checker.md @@ -128,10 +128,11 @@ The basic inputs are: The number of attempt fields (in the HTML), the number of `expected` values, and the number of `correct` values much match. -### JavaScript strings +### JavaScript notation -The lab data is expressed using JavaScript strings. -There's more than one way to express a string in JavaScript, each +The lab data is expressed using JavaScript, primarily as +JavaScript strings. +There's more than one way to express a string in JavaScript, and each has its advantages: * "..." - double-quoted string. You don't need to do anything special to @@ -148,6 +149,15 @@ has its advantages: These are often useful for patterns. Use ${BACKQUOTE} for ` and ${DOLLAR} for $. +JavaScript allows trailing commas, and we encourage using them. +In other words, +a list in JavaScript can have the form `[ 'a', 'b', 'c', ]` +(note the trailing comma after `'c'`). +Using trailing commas reduces the likelihood of +a common error: forgetting to add a comma when you add an item to a list. +Using trailing commas means that when you add a new item (`'d'`) at the end, +you *already* have the comma ready for use. + ### Expressing correct answer patterns The patterns used for `correct` and `hints` @@ -299,6 +309,8 @@ Here's an explanation of this pattern: This that one of the following patterns is allowed: `'id'` or `"id"` or `id` (and nothing else). Again, the space after it means 0+ spaces are allowed. + WARNING: If you use JavaScript raw strings or templates, you + need to escape the backquote (`) character. 5. The `\)` matches a literal close parenthesis, while `\.` matches a literal period. diff --git a/docs/labs/csp1.js b/docs/labs/csp1.js index 078e7810..2edf15af 100644 --- a/docs/labs/csp1.js +++ b/docs/labs/csp1.js @@ -7,8 +7,8 @@ info = examples: [ [ "import express from \"express\";" - ] - ] + ], + ], }, { absent: "const", @@ -20,21 +20,21 @@ info = examples: [ [ "const" ], [ "consthelmet = " ] - ] + ], }, { present: String.raw`require \( helmet \)`, text: "The parameter of a requirement statement must be string. Surround the term helment with double-quotes.", examples: [ [ " const helmet = require(helmet);" ] - ] + ], }, { absent: "; $", text: "JavaScript doesn''t require semicolon terminators, but the rest of the code uses them. You should try to match a coding style when modifying existing code unless there''s an important reason not to. Please update the first statment.", examples: [ [ " const helmet = require(\"helmet\")" ] - ] + ], }, { absent: String.raw`\s* app \. use \( helmet \( \{`, @@ -83,7 +83,7 @@ info = }, { text: "I do not have more specific hints to provide. Please ensure that the parentheses, braces, and brackets pair correctly, as that is often the problem." - } + }, ], expected: [ 'const helmet = require("helmet");', @@ -93,7 +93,7 @@ info = "script-src": ["'self'", "https://example.com"], "style-src": ["'self'"] }, - } + }, }));` ], correct: [ @@ -107,4 +107,4 @@ info = \} ,? \} \) \) ; \s*` ], -} +}; diff --git a/docs/labs/deserialization.js b/docs/labs/deserialization.js index befeaa75..a9427d16 100644 --- a/docs/labs/deserialization.js +++ b/docs/labs/deserialization.js @@ -28,7 +28,7 @@ info = { term: "CONDALL", value: "(COND0 && (COND1 && COND2|COND2 && COND1))" - } + }, ], hints: [ { @@ -61,8 +61,8 @@ info = [ "const data = JSON.parse(base64Decoded);", "if data.username {\n" - ] - ] + ], + ], }, { absent: String.raw`data \. username @@ -100,9 +100,9 @@ info = [ "const data = JSON.parse(base64Decoded);", "if (typeof data.username == 'string' && data.username.length < 20 && data.username) {" - ] - ] - } + ], + ], + }, ], expected: [ ' const data = JSON.parse(base64Decoded);', @@ -128,12 +128,12 @@ info = [ "const data = JSON.parse(base64Decoded);", "if (data.username && typeof data.username == 'string' && (data.username.length < 20)) {" - ] + ], ], failures: [ [ "const data = JSON.parse(base64Decoded);", "if (data.username && (typeof data.username == 'string')) && (data.username.length < 20)) {" - ] - ] -} + ], + ], +}; diff --git a/docs/labs/format-strings.js b/docs/labs/format-strings.js index 9d528b37..bba84e63 100644 --- a/docs/labs/format-strings.js +++ b/docs/labs/format-strings.js @@ -22,7 +22,7 @@ info = absent: String.raw`\'\{event.level\},\{event.message\}\' `, text: "The constant text `'{event.level},{event.message}'` should be present." - } + }, ], expected: [ String.raw`def format_event(new_event): @@ -31,4 +31,4 @@ info = correct: [ String.raw`(\r?\n)*def\x20+format_event\x20*\( new_event \)\x20*:(\r?\n)\x20+return\x20+'{event\.level},{event\.message}'\x20*\.\x20*format\x20*\( event = new_event \) \s*` ], -} +}; diff --git a/docs/labs/free.js b/docs/labs/free.js index 4cf2e3de..df4ab7d3 100644 --- a/docs/labs/free.js +++ b/docs/labs/free.js @@ -7,8 +7,8 @@ info = examples: [ [ "free(s);\nasprintf(&result, \"pre_%s_post\", s);" - ] - ] + ], + ], }, { present: String.raw`\s* asprintf \(`, @@ -17,8 +17,8 @@ info = examples: [ [ "asprintf(&result, \"\"pre_%s_post\"\", s);" - ] - ] + ], + ], }, { absent: "return", @@ -30,8 +30,8 @@ info = examples: [ [ "asprintf(&result, \"pre_%s_post\", s);\nfree(s);\nreturn result" - ] - ] + ], + ], }, { present: String.raw`\s* return result ; free \s*`, @@ -39,9 +39,9 @@ info = examples: [ [ "asprintf(&result, \"pre_%s_post\", s);\nreturn result;\nfree(s);" - ] - ] - } + ], + ], + }, ], expected: [ ` asprintf(&result, "pre_%s_post", s); @@ -54,4 +54,4 @@ info = free \( s \) ; return result ; \s*` ], -} +}; diff --git a/docs/labs/handling-errors.js b/docs/labs/handling-errors.js index 1d656aba..c62fa535 100644 --- a/docs/labs/handling-errors.js +++ b/docs/labs/handling-errors.js @@ -17,7 +17,7 @@ info = [ " throw NEW Error(\"Division by zero is forbidden\");" ], [ " throw new error(\"Division by zero is forbidden\");" ], [ " throw new ERROR(\"Division by zero is forbidden\");" ] - ] + ], }, { index: 0, @@ -26,7 +26,7 @@ info = examples: [ [ " return { success: false, message: \"Division by zero is forbidden\" };" ], [ " return \"Division by zero is forbidden\" ;" ] - ] + ], }, { index: 1, @@ -34,7 +34,7 @@ info = text: "Use the return keyword to return the result of the division.", examples: [ [ " a / b ;" ] - ] + ], }, { index: 1, @@ -48,8 +48,8 @@ info = [ "throw new Error(\"Division by zero is forbidden\");", " return { result: a / b };" - ] - ] + ], + ], }, { index: 2, @@ -60,8 +60,8 @@ info = "throw new Error(\"Division by zero is forbidden\");", "return a / b;", " const result = divide(10, 2);" - ] - ] + ], + ], }, { index: 2, @@ -72,8 +72,8 @@ info = "throw new Error(\"Division by zero is forbidden\");", "return a / b;", " try { const result = divide(10 ,2); if( result.success) { console.log ( \"Result:\", result ); " - ] - ] + ], + ], }, { index: 2, @@ -84,8 +84,8 @@ info = "throw new Error(\"Division by zero is forbidden\");", "return a / b;", " try { const result = divide(10 ,2); console.log ( \"Result:\", result.result ); " - ] - ] + ], + ], }, { index: 2, @@ -96,8 +96,8 @@ info = "throw new Error(\"Division by zero is forbidden\");", "return a / b;", " try { const result = divide(10 ,2); console.log ( \"Result:\", result ); }" - ] - ] + ], + ], }, { index: 2, @@ -108,8 +108,8 @@ info = "throw new Error(\"Division by zero is forbidden\");", "return a / b;", " try { const result = divide(10 ,2); console.log ( \"Result:\", result ); } catch {}" - ] - ] + ], + ], }, { index: 2, @@ -120,8 +120,8 @@ info = "throw new Error(\"Division by zero is forbidden\");", "return a / b;", " try { const result = divide(10 ,2); console.log ( \"Result:\", result ); } catch (foo) {" - ] - ] + ], + ], }, { index: 2, @@ -137,9 +137,9 @@ info = "throw new Error(\"Division by zero is forbidden\");", "return a / b;", " try { const result = divide(10 ,2); console.log ( \"Result:\", result ); } catch (err) { console.error('Error', result );" - ] - ] - } + ], + ], + }, ], expected: [ 'throw new Error("Division by zero is forbidden");', @@ -164,4 +164,4 @@ info = err \. message \) ; \} \s*` ], -} +}; diff --git a/docs/labs/hardcoded.js b/docs/labs/hardcoded.js index 506b731b..8cea1d22 100644 --- a/docs/labs/hardcoded.js +++ b/docs/labs/hardcoded.js @@ -46,7 +46,7 @@ info = System \. getenv \( "PASSWORD" \) \, System \. getenv \( "USERNAME" \) \) \; \s* $`, text: "The order of parameters is wrong. Provide the url, then the username, then the password. You're providing the url, then the password, then the username, which swaps the second and third parameters." - } + }, ], expected: [ `conn = DriverManager.getConnection(url, @@ -57,4 +57,4 @@ info = \s* System \. getenv \( "USERNAME" \) \, \s* System \. getenv \( "PASSWORD" \) \) \; \s*` ], -} +}; diff --git a/docs/labs/hello.js b/docs/labs/hello.js index d65588a5..1650ff78 100644 --- a/docs/labs/hello.js +++ b/docs/labs/hello.js @@ -6,7 +6,7 @@ info = text: "Please use the form console.log(...);", text_ja: "console.log(...); の形式を使用してください。", examples: [ [ "" ], [ "foo" ] - ] + ], }, { present: "Goodbye", @@ -63,7 +63,7 @@ info = text: "Please end this statement with a semicolon. JavaScript does not require a semicolon in this case, but usually when modifying source code you should follow the style of the current code.", text_ja: "このステートメントはセミコロンで終了してください。この場合、JavaScript ではセミコロンは必要ありませんが、通常、ソース コードを変更する場合は、現在のコードのスタイルに従う必要があります。", examples: [ [ " console.log(\"Hello, world!\") " ] ] - } + }, ], expected: ['console.log("Hello, world!");'], correct: @@ -91,6 +91,6 @@ info = [ String.raw`\s* foo \s+ bar \\string\\ \s*`, String.raw`\s*foo\s+bar\s*\\string\\\s*` - ] - ] + ], + ], }; diff --git a/docs/labs/input1.js b/docs/labs/input1.js index 5af0ae82..5ccd121a 100644 --- a/docs/labs/input1.js +++ b/docs/labs/input1.js @@ -6,7 +6,7 @@ info = text: "This is a parameter, it must end with a comma.", examples: [ [ " " ] - ] + ], }, { absent: String.raw`query \( ["'${BACKQUOTE}]id["'${BACKQUOTE}] \)`, @@ -14,14 +14,14 @@ info = examples: [ [ "," ], [ " query()," ] - ] + ], }, { present: String.raw`query \( ["'${BACKQUOTE}]id["'${BACKQUOTE}] \) [^. ]`, text: "After query(\"id\") use a period to invoke a verification method.", examples: [ [ " query('id')," ] - ] + ], }, { present: "(isint|Isint|IsInt|ISINT)", @@ -29,64 +29,64 @@ info = examples: [ [ " query('id').isint()," ], [ " query('id').IsInt()," ] - ] + ], }, { absent: "isInt", text: "Use isInt to determine if the parameter is an integer.", examples: [ [ " query('id').," ] - ] + ], }, { present: String.raw` query \( ["'${BACKQUOTE}]id["'${BACKQUOTE}] \).*\([^)]*$`, text: "After query(\"id\") you have an ( but there's no matching ).", examples: [ [ " query('id').isInt(," ] - ] + ], }, { absent: String.raw`isInt \(.*\)`, text: "isInt should be followed by (...).", examples: [ [ " query('id').isInt," ] - ] + ], }, { present: String.raw`\{[^}]*$`, text: "You have started an object using { but there's no matching }.", examples: [ [ " query('id').isInt({)," ] - ] + ], }, { absent: String.raw`isInt \( \{.*\} \)`, text: "Inside the parenthesis of isInt() you should have an object like {...}.", examples: [ [ " query('id').isInt()," ] - ] + ], }, { absent: "min", text: "Use min: to specify a minimum value.", examples: [ [ " query('id').isInt({})," ] - ] + ], }, { absent: "max", text: "Use max: to specify a minimum value.", examples: [ [ " query('id').isInt({min: 1})," ] - ] + ], }, { present: "max.*min", text: "JavaScript allows hash entries to be in any order, but this can be confusing to humans. Conventionally minimum values are given before maximum values; please follow that convention.", examples: [ [ " query('id').isInt({max: 9999, min: 1})," ] - ] - } + ], + }, ], expected: [ "query('id').isInt({min: 1, max: 9999})," @@ -98,11 +98,11 @@ info = successes: [ [ " query ( 'id' ) . isInt ( {min: 1 , max: 9999 } ) ," ], [ " query ( `id` ) . isInt ( {min: 1 , max: 9_999 } ) , " ], - [ "query ( \"id\" ) . isInt ( {min: 1 , max: 9_999 } ) ," ] + [ "query ( \"id\" ) . isInt ( {min: 1 , max: 9_999 } ) ," ], ], failures: [ [ " query," ], [ "query('id').isint({min: 1, max: 9999})" ], - [ "query('id').isInt({min: 1, max: 9999})" ] - ] -} + [ "query('id').isInt({min: 1, max: 9999})" ], + ], +}; diff --git a/docs/labs/input2.js b/docs/labs/input2.js index 70890835..1a7c5db1 100644 --- a/docs/labs/input2.js +++ b/docs/labs/input2.js @@ -52,7 +52,7 @@ info = { present: String.raw`\s*, , $`, text: "You have two commas at the end. Use only one. You may need to scroll or increase the text area to see both of them." - } + }, ], expected: [ String.raw` query('id').isLength({max:80}). @@ -77,7 +77,7 @@ info = ], [ " query (`id`) . isLength( {max:80}).matches(/^[A-Z]{2}-\\d+-[0-9]+$/ ) , " - ] + ], ], failures: [ [ @@ -96,4 +96,4 @@ info = "query(`id`).isLength( {max:80}).matches(/^[A-Z]{2}- \\d+-[0-9]+$/)," ], ], -} +}; diff --git a/docs/labs/oob1.js b/docs/labs/oob1.js index f87acd8c..891b7ae5 100644 --- a/docs/labs/oob1.js +++ b/docs/labs/oob1.js @@ -20,7 +20,7 @@ info = { absent: "return", text: "Need \"return 0;\" to skip attempts to send a too-long response." - } + }, ], definitions: [ { @@ -84,4 +84,4 @@ info = return 0;` ], ], -} +}; diff --git a/docs/labs/redos.js b/docs/labs/redos.js index 1d07145d..b858fccb 100644 --- a/docs/labs/redos.js +++ b/docs/labs/redos.js @@ -70,7 +70,7 @@ info = { present: String.raw`\[0-9[Aa]-[Zz]\]`, text: "It's conventional to list letters first, so use [A-Z0-9] not [0-9A-Z]" - } + }, ], expected: [ "query('id').isLength({max:50}).matches( /^[A-Z0-9]+$/ ),", @@ -87,4 +87,4 @@ info = failures: [ [ "query('id').isLength({max:50}).matches( /^[A-Z]+$/ ),", ], ], -} +}; diff --git a/docs/labs/regex0.js b/docs/labs/regex0.js index 2d68b5dc..4d65cebb 100644 --- a/docs/labs/regex0.js +++ b/docs/labs/regex0.js @@ -14,14 +14,14 @@ info = text: "Regexes are normally case-sensitive. Use a lowercase c.", examples: [ [ "C" ] - ] + ], }, { absent: "c", text: "If you are searching for \"cat\" you need to look for a \"c\"", examples: [ [ "x" ] - ] + ], }, { absent: "cat", @@ -46,7 +46,7 @@ info = absent: String.raw`B(\+|B\*)`, index: 1, text: "Use \"B+\" to indicate \"one or more B\". You could also write \"BB*\"." - } + }, ], expected: [ 'cat', @@ -69,6 +69,6 @@ info = [ "\\s*", "" - ] - ] -} + ], + ], +}; diff --git a/docs/labs/regex1.js b/docs/labs/regex1.js index 13bbf51f..c2fca851 100644 --- a/docs/labs/regex1.js +++ b/docs/labs/regex1.js @@ -6,42 +6,42 @@ info = text: "In JavaScript a constant regular expression is surrounded by forward slashes like /PATTERN/. However, for this exercise we only want the text inside the slashes (the pattern itself).", examples: [ [ "/" ] - ] + ], }, { present: "[\"'`]", text: "In this exercise we only want the regular expression pattern itself. There is no need to use any kind of quote mark.", examples: [ [ "'" ] - ] + ], }, { absent: String.raw`^\^`, text: "For input validation, start with '^' to indicate a full match.", examples: [ [ "(Y|N)" ] - ] + ], }, { present: String.raw`\\[Zz]`, text: "The ECMAScript (JavaScript) specification does not support \\Z or \\z.", examples: [ [ "^Y|N\\z" ] - ] + ], }, { absent: String.raw`\$$`, text: "For input validation, end with '$' to indicate a full match.", examples: [ [ "^(Y|N)" ] - ] + ], }, { absent: String.raw`[\|\[]`, text: "Consider using [YN], to match either a Y or an N.", examples: [ [ "^$" ] - ] + ], }, { present: String.raw`\|`, @@ -49,14 +49,14 @@ info = text: "If you use \"|\" you must parentheses or the precedence will be wrong. For example, \"^A|B$\" accepts anything beginning with A, and it also accepts anything ending with B. That is not what you want.", examples: [ [ "^Y|N$" ] - ] + ], }, { present: " ", text: "Spaces normally match spaces in a regex. Do not use them in this case, because a space is not one of the allowed characters.", examples: [ [ "^[YN] $" ] - ] + ], }, { absent: String.raw`^\^`, @@ -64,7 +64,7 @@ info = text: "For input validation, start with '^' to indicate a full match.", examples: [ [ "^[YN]$", "" ] - ] + ], }, { absent: String.raw`\$$`, @@ -72,7 +72,7 @@ info = text: "For input validation, end with '$' to indicate a full match.", examples: [ [ "^[YN]$", "^" ] - ] + ], }, { absent: String.raw`\[A-Z\]`, @@ -80,7 +80,7 @@ info = text: "You can use [A-Z] to match one uppercase Latin letter (A through Z).", examples: [ [ "^[YN]$", "^$" ] - ] + ], }, { present: String.raw`\^\[A-Z\]\*`, @@ -99,7 +99,7 @@ info = text: "You can use [A-Z]+ to match one or more uppercase Latin letters.", examples: [ [ "^[YN]$", "^[A-Z]$" ] - ] + ], }, { present: "True", @@ -160,7 +160,7 @@ info = present: String.raw`\[A-Z\](\*|\+)`, index: 4, text: "In this case we are only matching one letter, not many of them. Do not use \"*\" or \"+\" after [A-Z]." - } + }, ], expected: [ '^[YN]$', @@ -187,6 +187,6 @@ info = [ "\\s*", "" - ] - ] -} + ], + ], +}; diff --git a/docs/labs/shell-injection.js b/docs/labs/shell-injection.js index 2488ca3d..748332c5 100644 --- a/docs/labs/shell-injection.js +++ b/docs/labs/shell-injection.js @@ -17,8 +17,8 @@ info = [ " clean_dir = dir_to_list", " subprocess.run(f\"ls -l {dir_to_list}\", shell=True)" - ] - ] + ], + ], }, { absent: String.raw`clean_dir = re \. sub \(`, @@ -28,8 +28,8 @@ info = [ " clean_dir re.sub = dir_to_list", " subprocess.run(f\"ls -l {dir_to_list}\", shell=True)" - ] - ] + ], + ], }, { present: "PATTERN", @@ -38,8 +38,8 @@ info = [ " clean_dir = re.sub(PATTERN, PATTERN, dir_to_list)", " subprocess.run(f\"ls -l {dir_to_list}\", shell=True)" - ] - ] + ], + ], }, { absent: String.raw`re \. sub \( r`, @@ -56,8 +56,8 @@ info = [ " clean_dir = re.sub(r'([^a-zA-Z0-9])', '', dir_to_list)", " subprocess.run(f\"ls -l {dir_to_list}\", shell=True)" - ] - ] + ], + ], }, { absent: String.raw`re \. sub \( r?['"]\[`, @@ -66,8 +66,8 @@ info = [ " clean_dir = re.sub(r'', '', dir_to_list)", " subprocess.run(f\"ls -l {dir_to_list}\", shell=True)" - ] - ] + ], + ], }, { absent: String.raw`re \. sub \( r?['"]\[\^`, @@ -76,8 +76,8 @@ info = [ " clean_dir = re.sub(r'[a-zA-Z0-9]', '', dir_to_list)", " subprocess.run(f\"ls -l {dir_to_list}\", shell=True)" - ] - ] + ], + ], }, { absent: "a-zA-Z0-9", @@ -86,8 +86,8 @@ info = [ " clean_dir = re.sub(r'[^]', '', dir_to_list)", " subprocess.run(f\"ls -l {dir_to_list}\")" - ] - ] + ], + ], }, { absent: String.raw`re \. sub \( r?('\[\^a-zA-Z0-9\]'|"\[\^a-zA-Z0-9\]") , r?(''|"")`, @@ -96,8 +96,8 @@ info = [ " clean_dir = re.sub(r'[^a-zA-Z0-9]', NOWWHAT, dir_to_list)", " subprocess.run(f\"ls -l {dir_to_list}\", shell=True)" - ] - ] + ], + ], }, { absent: "subprocess.run", @@ -112,8 +112,8 @@ info = [ " clean_dir = re.sub(r'[^a-zA-Z0-9]', '', dir_to_list)", " subprocess.run(f\"ls -l {dir_to_list}\", shell=True)" - ] - ] + ], + ], }, { present: String.raw`f["']ls\s+-l`, @@ -123,8 +123,8 @@ info = [ " clean_dir = re.sub(r'[^a-zA-Z0-9]', '', dir_to_list)", " subprocess.run(f\"ls -l {dir_to_list}\")" - ] - ] + ], + ], }, { present: String.raw`["']ls\s+-l`, @@ -134,8 +134,8 @@ info = [ " clean_dir = re.sub(r'[^a-zA-Z0-9]', '', dir_to_list)", " subprocess.run(\"ls -l {dir_to_list}\")" - ] - ] + ], + ], }, { present: String.raw`subprocess \. run \( [A-Za-z0-9"']`, @@ -145,8 +145,8 @@ info = [ " clean_dir = re.sub(r'[^a-zA-Z0-9]', '', dir_to_list)", " subprocess.run(\"ls\", \"-l\", clean_dir)" - ] - ] + ], + ], }, { present: String.raw`\{(dir_to_list|clean_dir)\}`, @@ -156,8 +156,8 @@ info = [ " clean_dir = re.sub(r'[^a-zA-Z0-9]', '', dir_to_list)", " subprocess.run([\"ls\", \"-l\", {dir_to_list}])" - ] - ] + ], + ], }, { present: String.raw`dir_to_list\"`, @@ -177,8 +177,8 @@ info = [ " clean_dir = re.sub(r'[^a-zA-Z0-9]', '', dir_to_list)", " subprocess.run([\"ls\", \"-l\", dir_to_list])" - ] - ] + ], + ], }, { absent: String.raw`run \(.*\)`, @@ -188,8 +188,8 @@ info = [ " clean_dir = re.sub(r'[^a-zA-Z0-9]', '', clean_dir)", " subprocess.run([\"ls\", \"-l\", clean_dir]" - ] - ] + ], + ], }, { absent: String.raw`run \( \[.*\]`, @@ -199,8 +199,8 @@ info = [ " clean_dir = re.sub(r'[^a-zA-Z0-9]', '', clean_dir)", " subprocess.run([\"ls\", \"-l\", clean_dir)" - ] - ] + ], + ], }, { absent: String.raw`^ subprocess . run \( \[ ('ls'|"ls") , ('-l'|"-l") , clean_dir \] \) $`, @@ -210,9 +210,9 @@ info = [ " clean_dir = re.sub(r'[^a-zA-Z0-9]', '', clean_dir)", " subprocess.run([\"ls\", \"-l\", clean_dir, foo])" - ] - ] - } + ], + ], + }, ], successes: [ [ @@ -226,7 +226,7 @@ info = [ " clean_dir = re.sub(r'[^a-zA-Z0-9]', '', dir_to_list)", " subprocess.run([\"ls\", \"-l\", clean_dir], shell=False)" - ] + ], ], failures: [ [ @@ -240,7 +240,7 @@ info = [ " clean_dir = re . sub( r'[^a-zA-Z0-9]' , '' , dir_to_list )", " subprocess . run ( [ \"ls\" , \"-l\" , clean_dir ] )" - ] + ], ], expected: [ String.raw` clean_dir = re.sub(r'[^a-zA-Z0-9]', '', dir_to_list)`, @@ -260,5 +260,4 @@ info = \[ ('ls'|"ls") , ('-l'|"-l") , clean_dir \] ( , shell = False )? \) \s*` ], - debug: true, -} +}; diff --git a/docs/labs/sql-injection.js b/docs/labs/sql-injection.js index e25ea171..bfe75f01 100644 --- a/docs/labs/sql-injection.js +++ b/docs/labs/sql-injection.js @@ -8,8 +8,8 @@ info = examples: [ [ "search_lastname" - ] - ] + ], + ], }, { absent: String.raw`\?`, @@ -24,8 +24,8 @@ info = [ "String QueryString =\n \"select * from authors where lastname = \" + \"?\" + \" ; \";\n", "" - ] - ] + ], + ], }, { absent: String.raw`\s* PreparedStatement\s+pstmt = connection \. @@ -53,7 +53,7 @@ info = absent: String.raw`\s* ResultSet\s+results = pstmt \. executeQuery \( \) \; \s*`, index: 1, text: "After using `setString` execute the query and place the results in `results`, something like `ResultSet results = pstmt.executeQuery();`" - } + }, ], expected: [ String.raw` String QueryString = "select * from authors where lastname=?"; @@ -76,4 +76,4 @@ info = String.raw`\s* pstmt \. setString \( 1 , search_lastname \) \; \s* ResultSet\s+results = pstmt \. executeQuery \( \) \; \s*`, ], -} +}; diff --git a/docs/labs/template.js b/docs/labs/template.js index b36ae4c8..dfcd56c5 100644 --- a/docs/labs/template.js +++ b/docs/labs/template.js @@ -42,5 +42,5 @@ info = [ "EXPECTED0", "EXPECTED" ], [ "EXPECTED0", "EXPECTED11" ] ], - // debug: true // to enable debug output -} + // debug: true, // to enable debug output +}; diff --git a/docs/labs/xss.js b/docs/labs/xss.js index 887444cd..8bf8bc0c 100644 --- a/docs/labs/xss.js +++ b/docs/labs/xss.js @@ -36,7 +36,7 @@ info = absent: String.raw`\+`, index: 2, text: "Our expected answer includes concatentation using `+`. We expect something like `Markup('Original name='` followed by `+` followed by the variable containing the data that needs to be escaped." - } + }, ], expected: [ 'autoescape=select_autoescape()', @@ -48,4 +48,4 @@ info = String.raw`\s* < h1 >Hello\x20{{ person }}!< /h1 > \s*`, String.raw`\s* result = Markup \( ('Original name='|"Original name=") \) \+ name \s*` ], -} +};