diff --git a/textcode/fmt_jsonescape.c b/textcode/fmt_jsonescape.c index b86a471..9b4f808 100644 --- a/textcode/fmt_jsonescape.c +++ b/textcode/fmt_jsonescape.c @@ -3,6 +3,7 @@ #include "textcode.h" #include "str.h" #include "scan.h" +#include "case.h" #include "haveinline.h" /* src is UTF-8 encoded */ @@ -12,6 +13,13 @@ size_t fmt_jsonescape(char* dest,const char* src,size_t len) { char c; for (i=0; i tag in HTML, + * and the string is attacker controlled and contains "", + * that would allow cross site scripting. So we escape that here. */ + if (len-i>=9 && case_equalb(s+i+1,8,"/script>")) + goto unicodeescape; + goto noneed; case '\\': case '"': c=s[i]; @@ -29,6 +37,7 @@ escape: case '\f': c='f'; goto escape; default: if (s[i]<' ') { +unicodeescape: if (dest) { dest[written]='\\'; dest[written+1]='u'; @@ -68,6 +77,7 @@ escape: i+=j-1; /* -1 because the for loop will also add 1 */ break; } else { +noneed: if (dest) dest[written]=s[i]; ++written; } @@ -94,5 +104,6 @@ int main() { * anymore. This test will fail now: assert(fmt_jsonescape(buf,"\xf0\x9f\x92\xa9x",5)==13 && !memcmp(buf,"\\ud83d\\udca9x",13)); */ assert(fmt_jsonescape(buf,"a\x81x",3)==4 && !memcmp(buf,"a\xc2\x81x",4)); + assert(fmt_jsonescape(buf,"",9)==14 && !memcmp(buf,"\\u003c/Script>",14)); } #endif