Changeset b4b8f1e


Ignore:
Timestamp:
2014-03-02T00:37:43Z (10 years ago)
Author:
Wilmer van der Gaast <wilmer@…>
Branches:
master
Children:
b4008a5
Parents:
35987a1
Message:

Unicode parsing fix in JSON parser: JSON can contain UTF-16 surrogate pairs
(used to encode >16-bit chars). Added code to parse those *and* the ability
to encode >16-bit Unicode in UTF-8. Also sending this upstream. This should
fix #1121.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • lib/json.c

    r35987a1 rb4b8f1e  
    4949#include <math.h>
    5050
    51 typedef unsigned short json_uchar;
     51typedef unsigned int json_uchar;
    5252
    5353static unsigned char hex_value (json_char c)
     
    298298                    }
    299299
    300                     uc_b1 = uc_b1 * 16 + uc_b2;
    301                     uc_b2 = uc_b3 * 16 + uc_b4;
    302 
    303                     uchar = ((json_char) uc_b1) * 256 + uc_b2;
    304 
    305                     if (sizeof (json_char) >= sizeof (json_uchar) || (uc_b1 == 0 && uc_b2 <= 0x7F))
     300                    uc_b1 = (uc_b1 << 4) | uc_b2;
     301                    uc_b2 = (uc_b3 << 4) | uc_b4;
     302                    uchar = (uc_b1 << 8) | uc_b2;
     303
     304                    if ((uchar & 0xF800) == 0xD800) {
     305                        json_uchar uchar2;
     306                       
     307                        if (end - i < 6 || (*++ i) != '\\' || (*++ i) != 'u' ||
     308                            (uc_b1 = hex_value (*++ i)) == 0xFF || (uc_b2 = hex_value (*++ i)) == 0xFF
     309                              || (uc_b3 = hex_value (*++ i)) == 0xFF || (uc_b4 = hex_value (*++ i)) == 0xFF)
     310                        {
     311                            sprintf (error, "Invalid character value `%c` (at %d:%d)", b, cur_line, e_off);
     312                            goto e_failed;
     313                        }
     314
     315                        uc_b1 = (uc_b1 << 4) | uc_b2;
     316                        uc_b2 = (uc_b3 << 4) | uc_b4;
     317                        uchar2 = (uc_b1 << 8) | uc_b2;
     318                       
     319                        uchar = 0x010000 | ((uchar & 0x3FF) << 10) | (uchar2 & 0x3FF);
     320                    }
     321
     322                    if (sizeof (json_char) >= sizeof (json_uchar) || (uchar <= 0x7F))
    306323                    {
    307324                       string_add ((json_char) uchar);
     
    314331                           string_length += 2;
    315332                        else
    316                         {  string [string_length ++] = 0xC0 | ((uc_b2 & 0xC0) >> 6) | ((uc_b1 & 0x7) << 2);
    317                            string [string_length ++] = 0x80 | (uc_b2 & 0x3F);
     333                        {  string [string_length ++] = 0xC0 | (uchar >> 6);
     334                           string [string_length ++] = 0x80 | (uchar & 0x3F);
    318335                        }
    319336
     
    321338                    }
    322339
     340                    if (uchar <= 0xFFFF) {
     341                        if (state.first_pass)
     342                           string_length += 3;
     343                        else
     344                        {  string [string_length ++] = 0xE0 | (uchar >> 12);
     345                           string [string_length ++] = 0x80 | ((uchar >> 6) & 0x3F);
     346                           string [string_length ++] = 0x80 | (uchar & 0x3F);
     347                        }
     348                       
     349                        break;
     350                    }
     351
    323352                    if (state.first_pass)
    324                        string_length += 3;
     353                       string_length += 4;
    325354                    else
    326                     {  string [string_length ++] = 0xE0 | ((uc_b1 & 0xF0) >> 4);
    327                        string [string_length ++] = 0x80 | ((uc_b1 & 0xF) << 2) | ((uc_b2 & 0xC0) >> 6);
    328                        string [string_length ++] = 0x80 | (uc_b2 & 0x3F);
     355                    {  string [string_length ++] = 0xF0 | (uchar >> 18);
     356                       string [string_length ++] = 0x80 | ((uchar >> 12) & 0x3F);
     357                       string [string_length ++] = 0x80 | ((uchar >> 6) & 0x3F);
     358                       string [string_length ++] = 0x80 | (uchar & 0x3F);
    329359                    }
    330360
Note: See TracChangeset for help on using the changeset viewer.