Skip to content

Commit

Permalink
Handle escaped forward slashes \\/ (#75)
Browse files Browse the repository at this point in the history
* Handle escaped forward slashes `\\/`

Forward slash (`/`) is prefixed with double backslash (`\\`)
in a JSON string. Although this is valid in JSON, this will fail
regex parsing in the rust `Regex` library, which will error when
parsing an escaped forward slash.

This string replacement ensures that escaped forward slashes do
not fail validation.

* Remove unnecessary import

---------

Co-authored-by: Sheldon Warkentin <sheldonw@forallsecure.com>
  • Loading branch information
swarkentin and Sheldon Warkentin committed Feb 2, 2023
1 parent 3a5824b commit 8c8826f
Showing 1 changed file with 60 additions and 5 deletions.
65 changes: 60 additions & 5 deletions src/json_schema/validators/formats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,12 +182,22 @@ impl super::Validator for Regex {
fn validate(&self, val: &Value, path: &str, _scope: &scope::Scope) -> super::ValidationState {
let string = nonstrict_process!(val.as_str(), path);

match regex::Regex::new(string) {
Ok(_) => super::ValidationState::new(),
Err(_) => val_error!(errors::Format {
// Forward slash ('/') is prefixed with double backslash ('\\')
// in a JSON string. Although this is valid in JSON, this will fail
// regex parsing in the rust Regex library. This string replacement
// ensures that escaped forward slashes do not fail validation.
let string = string.replace(r"\/", "/");

match regex::Regex::new(&string) {
Ok(_) => {
super::ValidationState::new()
}
Err(er) => {
val_error!(errors::Format {
path: path.to_string(),
detail: "Malformed regex".to_string()
}),
detail: format!("Malformed regex - {}", er)
})
}
}
}
}
Expand Down Expand Up @@ -290,3 +300,48 @@ impl super::Validator for UriTemplate {
super::ValidationState::new()
}
}


#[cfg(test)]
pub mod tests {
use super::Regex;
use crate::json_schema::validators::Validator;
use crate::json_schema::{Scope, ValidationState};

#[test]
fn validate_valid_empty_regex() {
let result = validate_regex("");
assert!(result.errors.is_empty())
}

#[test]
fn validate_valid_regex_simple() {
let result = validate_regex("^[a-z][a-z0-9]{0,10}$");
assert!(result.errors.is_empty())
}

#[test]
fn validate_valid_regex_with_double_escaped_forward_slash() {
let result = validate_regex("\\w+:(\\/?\\/?)[^\\s]+");
assert!(result.errors.is_empty())
}

#[test]
fn validate_invalid_regex() {
let result = validate_regex("FOO\\");
assert_eq!(result.errors.len(), 1);

let only_err = result.errors.get(0);
assert!(only_err.is_some());

let err = only_err.unwrap();
assert!(err.get_detail().is_some());
assert_eq!(err.get_detail().unwrap(), "Malformed regex - regex parse error:\n FOO\\\n ^\nerror: incomplete escape sequence, reached end of pattern prematurely")
}

fn validate_regex(json_string: &str) -> ValidationState {
let value = serde_json::value::Value::String(json_string.into());
let scope = Scope::new();
Regex {}.validate(&value, "/", &scope)
}
}

0 comments on commit 8c8826f

Please sign in to comment.