Skip to content

Commit

Permalink
Merge pull request #56 from ma8ma/sanitize-numeric-character-reference
Browse files Browse the repository at this point in the history
Sanitize numeric character reference
  • Loading branch information
yama-natuki committed Mar 17, 2019
2 parents 42631b8 + 13e8c52 commit a9aa0b1
Showing 1 changed file with 82 additions and 1 deletion.
83 changes: 82 additions & 1 deletion src/jdlib/miscutil.cpp
Expand Up @@ -1305,6 +1305,87 @@ int MISC::spchar_number_ln( const char* in_char, int& offset )
}


// 特定の変換が必要なコードポイントをチェックする
static int transform_7f_9f( int raw_point )
{
switch( raw_point ) {
case 0x80: return 0x20AC; // EURO SIGN (€)
case 0x82: return 0x201A; // SINGLE LOW-9 QUOTATION MARK (‚)
case 0x83: return 0x0192; // LATIN SMALL LETTER F WITH HOOK (ƒ)
case 0x84: return 0x201E; // DOUBLE LOW-9 QUOTATION MARK („)
case 0x85: return 0x2026; // HORIZONTAL ELLIPSIS (…)
case 0x86: return 0x2020; // DAGGER (†)
case 0x87: return 0x2021; // DOUBLE DAGGER (‡)
case 0x88: return 0x02C6; // MODIFIER LETTER CIRCUMFLEX ACCENT (ˆ)
case 0x89: return 0x2030; // PER MILLE SIGN (‰)
case 0x8A: return 0x0160; // LATIN CAPITAL LETTER S WITH CARON (Š)
case 0x8B: return 0x2039; // SINGLE LEFT-POINTING ANGLE QUOTATION MARK (‹)
case 0x8C: return 0x0152; // LATIN CAPITAL LIGATURE OE (Œ)
case 0x8E: return 0x017D; // LATIN CAPITAL LETTER Z WITH CARON (Ž)
case 0x91: return 0x2018; // LEFT SINGLE QUOTATION MARK (‘)
case 0x92: return 0x2019; // RIGHT SINGLE QUOTATION MARK (’)
case 0x93: return 0x201C; // LEFT DOUBLE QUOTATION MARK (“)
case 0x94: return 0x201D; // RIGHT DOUBLE QUOTATION MARK (”)
case 0x95: return 0x2022; // BULLET (•)
case 0x96: return 0x2013; // EN DASH (–)
case 0x97: return 0x2014; // EM DASH (—)
case 0x98: return 0x02DC; // SMALL TILDE (˜)
case 0x99: return 0x2122; // TRADE MARK SIGN (™)
case 0x9A: return 0x0161; // LATIN SMALL LETTER S WITH CARON (š)
case 0x9B: return 0x203A; // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK (›)
case 0x9C: return 0x0153; // LATIN SMALL LIGATURE OE (œ)
case 0x9E: return 0x017E; // LATIN SMALL LETTER Z WITH CARON (ž)
case 0x9F: return 0x0178; // LATIN CAPITAL LETTER Y WITH DIAERESIS (Ÿ)
default:
return 0xFFFD; // REPLACEMENT CHARACTER
}
}

//
// コードポイントが数値文字参照としてはエラーなら規定の値へ変換する
// 例えばサロゲートペアは'REPLACEMENT CHARACTER' (U+FFFD)を返す
//
// 参考文献 : Numeric character reference end state (HTML 5.3)
// https://www.w3.org/TR/html53/syntax.html#numeric-character-reference-end-state
//
static int sanitize_numeric_character_reference( int raw_point )
{
// NOTE: 記号や絵文字を速やかに処理できるよう順番が組まれている

bool parse_error = false;

// 基本多言語面(BMP)をおおまかにチェック
if( 0x009F < raw_point && raw_point < 0xD800 ) return raw_point;
// 特定のbitパターンの非文字と符号空間の範囲をチェック
else if( ( raw_point & 0xFFFE ) == 0xFFFE || raw_point > 0x10FFFF ) parse_error = true;
// bitパターンを除いたらBMPの一部と追加多言語面(SMP)以降をチェック
else if( 0xFDEF < raw_point ) return raw_point;
// サロゲートペアはエラー
else if( 0xD800 <= raw_point && raw_point <= 0xDFFF ) parse_error = true;

// 基本ラテン文字をチェック
else if( 0x001F < raw_point && raw_point < 0x007F ) return raw_point;
// 特定の変換が必要なコードポイントをチェック
else if( 0x007F <= raw_point && raw_point <= 0x009F ) return transform_7f_9f( raw_point );
// 最後に制御文字と非文字をチェック
// サロゲートペアは他の値より入力される可能性が高いので処理を優先している
else if( raw_point <= 0x0008 // Control character
|| raw_point == 0x000B // Control character (Vertical tab)
|| ( 0x000D <= raw_point && raw_point <= 0x001F ) // Control character
|| ( 0xFDD0 <= raw_point && raw_point <= 0xFDEF ) // Noncharacters
) {
parse_error = true;
}

if( parse_error ) {
#ifdef _DEBUG
std::cout << "Parse error for numeric character reference... " << raw_point << std::endl;
#endif
return 0xFFFD; // REPLACEMENT CHARACTER
}
return raw_point;
}

//
// 「&#数字;」形式の数字参照文字列を数字(int)に変換する
//
Expand All @@ -1331,7 +1412,7 @@ int MISC::decode_spchar_number( const char* in_char, const int offset, const int
if( offset == 2 ) num = atoi( str_num );
else num = strtol( str_num, NULL, 16 );

return num;
return sanitize_numeric_character_reference( num );
}


Expand Down

0 comments on commit a9aa0b1

Please sign in to comment.