Skip to content

Commit

Permalink
Merge pull request #753 from ossf/deserialization_no_yaml
Browse files Browse the repository at this point in the history
Deserialization no yaml
  • Loading branch information
david-a-wheeler authored Jan 29, 2025
2 parents c2466e4 + 5df103b commit 7756046
Show file tree
Hide file tree
Showing 2 changed files with 140 additions and 127 deletions.
128 changes: 1 addition & 127 deletions docs/labs/deserialization.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,137 +7,11 @@
<link rel="stylesheet" href="checker.css">
<script src="js-yaml.min.js"></script>
<script src="checker.js"></script>
<script src="deserialization.js"></script>
<link rel="license" href="https://creativecommons.org/licenses/by/4.0/">

<!-- See create_labs.md for how to create your own lab! -->

<!-- Sample expected answer -->
<script id="expected0" type="plain/text">
const data = JSON.parse(base64Decoded);
</script>
<!--
-->
<script id="expected1" type="plain/text">
if (data.username && typeof data.username == 'string' && data.username.length < 20) {
</script>

<!-- Full pattern of correct answer -->
<script id="correct0" type="plain/text">
\s* const data = JSON \. parse \( base64Decoded \) \; \s*
</script>
<script id="correct1" type="plain/text">
\s* if \( CONDALL \) \{ \s*
</script>

<script id="info" type="application/yaml">
---
# Allow condition subexpressions to be optionally surrounded by parentheses
# and allow the order to vary. This allows more real-world answers to be
# considered acceptable.
# Doing this is more easily done by buildigg up definitions,
# which is annoying to write but general.
definitions:
- term: COND0
value: |-
data \. username
- term: COND0
value: |-
(COND0|\( COND0 \))
- term: COND1
value: |-
typeof\s+data \. username == ('string'|"string"|`string`)
- term: COND1
value: |-
(COND1|\( COND1 \))
- term: COND2
value: |-
data \. username \. length < 20
- term: COND2
value: |-
(COND2|\( COND2 \))
# Only the first one is likely, but we may as well allow both possibilities.
# The first condition MUST be first because it checks if the value exists.
- term: CONDALL
value: |-
(COND0 && (COND1 && COND2|COND2 && COND1))
hints:
- absent: |
^ const data =
text: The first section should begin with `const data =`
- present: "json"
text: the JSON built-in global object is witten in uppercase.
- absent: |
JSON \. parse
text: Make a call to `JSON.parse` with the data retrieved, e.g.,
`JSON.parse(base64Decoded)` should be stored in `data`.
- present: |
\+
text: You should not have any concatenation (`+`) in the first section.
- absent: |
; $
text: JavaScript does not require semicolons at the end of a
statement, but since the other statements terminate with semicolons,
you should also terminate your statement with a semicolon to be consistent.
- absent: |-
^ if \(
index: 1
text: The second section should start with `if (` followed by a condition.
examples:
-
- const data = JSON.parse(base64Decoded);
- |
if data.username {
- absent: |
data \. username
index: 1
text: Check if the data object has a property called username. You can do this by referencing data.username.
- absent: \&\&
index: 1
text: To combine multiple conditions in JavaScript use &&. This operator means 'and', so both conditions must be true for the entire statement to pass.
- absent: typeof
index: 1
text: Use typeof to check the type of the operand's value.
You should have `typeof data.username == 'string'`
or similar.
- present: |
typeof data \. username == 'String'
index: 1
text: When using typeof, JavaScript expects "string" all lowercase.
- absent: length
index: 1
text: check if the length of the string is smaller than 20 characters.
Use the expression `data.username.length &lt; 20` to determine this.
- present: |-
^ if \(
absent: |-
^ if \( data \. username &&
index: 1
text: Begin the second section with `if ( data.username && ... `
because you must check if data is even present before you can check
various attributes of that data.
examples:
-
- "const data = JSON.parse(base64Decoded);"
- "if (typeof data.username == 'string' && data.username.length < 20 && data.username) {"
successes:
-
- const data = JSON.parse(base64Decoded);
- if (data.username && typeof data.username == 'string' && data.username.length < 20) {
-
- const data = JSON . parse ( base64Decoded ) ;
- if ( data . username && typeof data . username == 'string' && data . username.length < 20) {
-
- const data = JSON.parse(base64Decoded);
- if (data.username && (typeof data.username == 'string') && (data.username.length < 20)) {
-
- 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)) {
# debug: true
</script>
</head>
<body>
<!-- For GitHub Pages formatting: -->
Expand Down
139 changes: 139 additions & 0 deletions docs/labs/deserialization.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
info =
{
definitions: [
{
term: "COND0",
value: String.raw`data \. username`
},
{
term: "COND0",
value: String.raw`(COND0|\( COND0 \))`
},
{
term: "COND1",
value: String.raw`typeof\s+data \. username == ('string'|"string"|${BACKQUOTE}string${BACKQUOTE})`
},
{
term: "COND1",
value: String.raw`(COND1|\( COND1 \))`
},
{
term: "COND2",
value: String.raw`data \. username \. length < 20`
},
{
term: "COND2",
value: String.raw`(COND2|\( COND2 \))`
},
{
term: "CONDALL",
value: "(COND0 && (COND1 && COND2|COND2 && COND1))"
}
],
hints: [
{
absent: "^ const data =\n",
text: "The first section should begin with `const data =`"
},
{
present: "json",
text: "the JSON built-in global object is witten in uppercase."
},
{
absent: String.raw`JSON \. parse
`,
text: "Make a call to `JSON.parse` with the data retrieved, e.g., `JSON.parse(base64Decoded)` should be stored in `data`."
},
{
present: String.raw`\+
`,
text: "You should not have any concatenation (`+`) in the first section."
},
{
absent: "; $\n",
text: "JavaScript does not require semicolons at the end of a statement, but since the other statements terminate with semicolons, you should also terminate your statement with a semicolon to be consistent."
},
{
absent: String.raw`^ if \(`,
index: 1,
text: "The second section should start with `if (` followed by a condition.",
examples: [
[
"const data = JSON.parse(base64Decoded);",
"if data.username {\n"
]
]
},
{
absent: String.raw`data \. username
`,
index: 1,
text: "Check if the data object has a property called username. You can do this by referencing data.username."
},
{
absent: String.raw`\&\&`,
index: 1,
text: "To combine multiple conditions in JavaScript use &&. This operator means 'and', so both conditions must be true for the entire statement to pass."
},
{
absent: "typeof",
index: 1,
text: "Use typeof to check the type of the operand's value. You should have `typeof data.username == 'string'` or similar."
},
{
present: String.raw`typeof data \. username == 'String'
`,
index: 1,
text: "When using typeof, JavaScript expects \"string\" all lowercase."
},
{
absent: "length",
index: 1,
text: "check if the length of the string is smaller than 20 characters. Use the expression `data.username.length &lt; 20` to determine this."
},
{
present: String.raw`^ if \(`,
absent: String.raw`^ if \( data \. username &&`,
index: 1,
text: "Begin the second section with `if ( data.username && ... ` because you must check if data is even present before you can check various attributes of that data.",
examples: [
[
"const data = JSON.parse(base64Decoded);",
"if (typeof data.username == 'string' && data.username.length < 20 && data.username) {"
]
]
}
],
expected: [
' const data = JSON.parse(base64Decoded);',
` if (data.username && typeof data.username == 'string' && data.username.length < 20) {`
],
correct: [
String.raw`\s* const data = JSON \. parse \( base64Decoded \) \; \s*`,
String.raw`\s* if \( CONDALL \) \{ \s*`
],
successes: [
[
"const data = JSON.parse(base64Decoded);",
"if (data.username && typeof data.username == 'string' && data.username.length < 20) {"
],
[
"const data = JSON . parse ( base64Decoded ) ;",
"if ( data . username && typeof data . username == 'string' && data . username.length < 20) {"
],
[
"const data = JSON.parse(base64Decoded);",
"if (data.username && (typeof data.username == 'string') && (data.username.length < 20)) {"
],
[
"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)) {"
]
]
}

0 comments on commit 7756046

Please sign in to comment.