Skip to content
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