Upload
takesako
View
6.536
Download
7
Embed Size (px)
DESCRIPTION
PCREの記法(?R)(?0)(?1)を使うテクニック
Citation preview
(?R)
再帰的正規表現で JSON Validator を作ってみた再帰的正規表現で JSON Validator を作ってみた
PCRE の記法 (?R)(?0)(?1) を使うテクニック$json =~ /\A (
\s* (?: "(?:[^"\\]*|\\["\\bfnrt\/]|\\u[0-9A-Fa-f]{4})*" | -? (?= [1-9]|0(?!\d) ) \d+ (?:\.\d+)? (?:[eE] [+-]? \d+)? | true | false | null | \[ (?: (?1) (?: , (?1) )* )? \s* \] | \{ (?: \s*"(?:[^"\\]*|\\["\\bfnrt\/]|\\u[0-9A-Fa-f]{4})*"\s*:(?1) (?:,\s*"(?:[^"\\]*|\\["\\bfnrt\/]|\\u[0-9A-Fa-f]{4})*"\s*:(?1)
)*)? \s* \} ) \s*)\Z/sx;
JSON とは
JSON とはJSON とは
JavaScript Object NotationJavaScript の記法を元にしたデータ記述用言語
元々は JavaScript のサブセットとして考案var obj = eval( "(" + json_text + ")" );
JSON 文字列を eval すると JavaScript object になる
[ { "id" : 1001 , "name" : "foo" }, { "id" : 1002 , "name" : "bar" }]
JavaScript で受け取った JSON を eval すると… JavaScript で受け取った JSON を eval すると…
そのまま eval するのは大変危険「山田太郎(正常系)」
{ "name" : " 山田太郎 => (正常系 " }「山田 ” }),alert(24)//XSS 」
{ "name" : " 山田 "}),alert(24)// 太郎 " }
var json_text = ( { "name" : " 山田 "}, alert(24);//XSS " });var obj = eval("(" + json_text + ")");
CVE-2007-3227 : JSON における XSS 脆弱性CVE-2007-3227 : JSON における XSS 脆弱性
#to_json の HTML エスケープ漏れで XSSが発生
http://dev.rubyonrails.org/ticket/8371
JSON の規格(データ交換フォーマット)JSON の規格(データ交換フォーマット)
RFC4627 による定義The application/json Media Type for
JavaScript Object Notation (JSON)ECMA-262 による定義
ECMA-262 ECMAScript 言語仕様 5th edition15.12 The JSON object [PDF]
ISO/IEC 16262:2011他のプログラミング言語の JSON parser
PHP, Python, Java, Perl, C/C++...http://json.org/
JSON の構成要素JSON の構成要素
JSON stringJSON numberJSON arrayJSON objectJSON value特別な値3つ
truefalsenull
JSON string の定義JSON string の定義
例: "abc", "\t\n", " あ ", "\u3042"A string is a collection of zero or more
Unicode characters, wrapped in double quotes, using backslash escapes. A character is represented as a single character string.
JSON number の定義JSON number の定義
例: 0, 1, -2, 3.14, 9e3, 9000A number is very much like a C or Java
number, except that the octal and hexadecimal formats are not used.
JSON array の定義JSON array の定義
例: ["a", "b", "c"]An array is an ordered collection of values.
An array begins with [ (left bracket) and ends with ] (right bracket). Values are separated by , (comma).
JSON object の定義JSON object の定義
例: {"string": value, "key": value}An object is an unordered set of name/value
pairs. An object begins with { (left brace) and ends with } (right brace). Each name is followed by : (colon) and the name/value pairs are separated by , (comma).
JSON value の定義JSON value の定義
例: "abc", 123, {}, [], true, false, nullA value can be a string in double quotes, or
a number, or true or false or null, or an object or an array. These structures can be nested.[ [], [1, 2], ["a", "b"], {}, {"x": {"y": "z"}} ]
演習問題
Q. 以下の JSON は正しいフォーマットか?Q. 以下の JSON は正しいフォーマットか?
(1) JSON object のキーは "string"
{ apple: 1, beer: 2 }
{ "apple": 1, "beer": 2 }
Q. 以下の JSON は正しいフォーマットか?Q. 以下の JSON は正しいフォーマットか?
(2) 複数 value のカンマ区切り(最後){ "name" : "TAKESAKO, Yoshinori", "E-mail" : "[email protected]",}
{ "name" : "TAKESAKO, Yoshinori", "E-mail" : "[email protected]"}
Q. 以下の JSON は正しいフォーマットか?Q. 以下の JSON は正しいフォーマットか?
(3) JSON string の引用符は "" のみ
[ 0, 1, 2, 'abc', 'string' ]
[ 0, 1, 2, "abc", "string" ]
Q. 以下の JSON は正しいフォーマットか?Q. 以下の JSON は正しいフォーマットか?
(4) JSON number の符号に + はない
[ -3, 3.14, 1.23e2, +123.456 ]
[ -3, 3.14, 1.23e2, 123.456 ]
Q. 以下の JSON は正しいフォーマットか?Q. 以下の JSON は正しいフォーマットか?
(5) JavaScript comment は使用できない
[{ /* Bookmark */ "url": "http://cybozu.co.jp/", "memo": "Cybozu HP" // title}]
[{ "url": "http://cybozu.co.jp/", "memo": "Cybozu HP"}]
Q. 以下の JSON は正しいフォーマットか?Q. 以下の JSON は正しいフォーマットか?
(6) JSON number は 10 進数のみ
[ { "file": "a.out", "chmod": 0775 }, { "file": "a.cpp", "chmod": 0644 }]
[ { "file": "a.out", "chmod": 509 }, { "file": "a.cpp", "chmod": 420 }]
Q. 以下の JSON は正しいフォーマットか?Q. 以下の JSON は正しいフォーマットか?
(7) string number 以外の JSON value
[ "Boolean", True, False, Null ]
[ "Boolean", true, false, null ]
Q. 以下の JSON は正しいフォーマットか?Q. 以下の JSON は正しいフォーマットか?
(8) Unicode 文字の扱い
{ "a": "a あ A", "i": "i\u3044I" }
{ "a":"a\u3042A", "i":"i\u3044I" }
Q. 以下の JSON は正しいフォーマットか?Q. 以下の JSON は正しいフォーマットか?
(9) / のエスケープ
"<script src='/jquery.js'></script>"
"<script src='/jquery.js'><\/script>"
正規表現でチェックできる?
Perl で PCRE 拡張の記法を使うPerl で PCRE 拡張の記法を使う
(?(DEFINE) (?<foo> regexp1)(?<bar> regexp2) … )
(?&foo) (?&bar)$json =~ / (?(DEFINE) (?<string> (?:[^"\\]* | \\ ["\\bfnrt\/] | \\u[0-9A-Fa-f]{4} )* " ) (?<number> -? (?=[1-9]|0(?!\d))\d+(?:\.\d+)? (?:[eE] [+-]? \d+)? ) (?<boolean> true | false | null ) (?<array> \[ (?: (?&json) (?: , (?&json) )* )? \s* \] ) (?<pair> \s* (?&string) \s* : (?&json) ) (?<object> \{ (?: (?&pair) (?: , (?&pair) )* )? \s* \} ) (?<json> \s* (?: (?&number) | (?&boolean) | (?&string) | (?&array) | (?&object) ) \s* ) ) \A (?&json) \Z/sx;
これはわかりやすい
自分自身の正規表現にマッチ (?R)自分自身の正規表現にマッチ (?R)
PCRE の記法 (?R) が Perl でも使える!
“{{{}}}” にマッチ“xxxx{{{}}}}}}}zzzzzz” にもマッチ
以下の正規表現だとネストしてくれない…
/\{(?R)*\}/
/^ \{(?R)*\} $/
(?R)(?0)(?1)(?2) ・・・が使える!(?R)(?0)(?1)(?2) ・・・が使える!
任意のキャプチャ部分の再帰ができる
/\{(?R)*\}/
/^(\{(?1)*\})$/
/\{(?0)*\}/
/(\{(?1)*\})/
JSON Validator を作ってみるJSON Validator を作ってみる
PCRE の記法 (?1) を使うテクニック$json =~ /\A ( \s* (?: "(?:[^"\\]*|\\["\\bfnrt\/]|\\u[0-9A-Fa-f]{4})*" | -? (?= [1-9]|0(?!\d) ) \d+ (?:\.\d+)? (?:[eE] [+-]? \d+)? | true | false | null | \[ (?: (?1) (?: , (?1) )* )? \s* \] | \{(?: \s*"(?:[^"\\]*|\\["\\bfnrt\/]|\\u[0-9A-Fa-f]{4})*"\s*:(?1) (?:,\s*"(?:[^"\\]*|\\["\\bfnrt\/]|\\u[0-9A-Fa-f]{4})*"\s*:(?1)
)* )? \s* \} ) \s*)\Z/sx;
再帰的正規表現便利也