Skip to content

Escape closing tags in strings #51

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions ext/json/ext/generator/generator.c
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string)
unsigned long len = RSTRING_LEN(string), start = 0, end = 0;
const char *escape = NULL;
int escape_len;
unsigned char c;
unsigned char c, last_c = -1;
char buf[6] = { '\\', 'u' };

for (start = 0, end = 0; end < len;) {
Expand Down Expand Up @@ -271,13 +271,20 @@ static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string)
escape_len = 2;
break;
default:
end++;
continue;
if (c == '/' && last_c == '<') {
escape = "\\/";
escape_len = 2;
} else {
last_c = c;
end++;
continue;
}
break;
}
}
fbuffer_append(buffer, ptr + start, end - start);
fbuffer_append(buffer, escape, escape_len);
last_c = c;
start = ++end;
escape = NULL;
}
Expand Down
14 changes: 12 additions & 2 deletions java/src/json/ext/StringEncoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,17 @@ final class StringEncoder extends ByteListTranscoder {
void encode(ByteList src, ByteList out) {
init(src, out);
append('"');
int lastChar = -1;
while (hasNext()) {
handleChar(readUtf8Char());
int newChar = readUtf8Char();
handleChar(newChar, lastChar);
lastChar = newChar;
}
quoteStop(pos);
append('"');
}

private void handleChar(int c) {
private void handleChar(int c, int lastChar) {
switch (c) {
case '"':
case '\\':
Expand All @@ -68,6 +71,13 @@ private void handleChar(int c) {
case '\b':
escapeChar('b');
break;
case '/':
if (lastChar == '<') {
escapeChar('/');
} else {
quoteStart();
}
break;
default:
if (c >= 0x20 && c <= 0x7f ||
(c >= 0x80 && !asciiOnly)) {
Expand Down
7 changes: 6 additions & 1 deletion lib/json/pure/generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ def utf8_to_json(string) # :nodoc:
string << '' # XXX workaround: avoid buffer sharing
string.force_encoding(::Encoding::ASCII_8BIT)
string.gsub!(/["\\\x0-\x1f]/) { MAP[$&] }
string.gsub!("</", '<\/') # avoid "</script>"
string.force_encoding(::Encoding::UTF_8)
string
end
Expand All @@ -65,14 +66,17 @@ def utf8_to_json_ascii(string) # :nodoc:
s = JSON.iconv('utf-16be', 'utf-8', c).unpack('H*')[0]
s.gsub!(/.{4}/n, '\\\\u\&')
}
string.gsub!("</", '<\/') # avoid "</script>"
string.force_encoding(::Encoding::UTF_8)
string
rescue => e
raise GeneratorError, "Caught #{e.class}: #{e}"
end
else
def utf8_to_json(string) # :nodoc:
string.gsub(/["\\\x0-\x1f]/) { MAP[$&] }
string = string.gsub(/["\\\x0-\x1f]/) { MAP[$&] }
string.gsub!("</", '<\/') # avoid "</script>"
string
end

def utf8_to_json_ascii(string) # :nodoc:
Expand All @@ -89,6 +93,7 @@ def utf8_to_json_ascii(string) # :nodoc:
s = JSON.iconv('utf-16be', 'utf-8', c).unpack('H*')[0]
s.gsub!(/.{4}/n, '\\\\u\&')
}
string.gsub!("</", '<\/') # avoid "</script>"
string
rescue => e
raise GeneratorError, "Caught #{e.class}: #{e}"
Expand Down
6 changes: 6 additions & 0 deletions tests/test_json_generate.rb
Original file line number Diff line number Diff line change
Expand Up @@ -176,4 +176,10 @@ def test_depth
assert_raises(JSON::NestingError) { ary.to_json(s) }
assert_equal 19, s.depth
end


def test_no_close_tag
assert_equal '["<\/script>"]', generate(["</script>"])
assert_equal '["<\/SCRIPT>"]', generate(["</SCRIPT>"])
end
end