/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "buffer.h"
#include "hex-dec.h"
#include "unichar.h"
#include "istream-private.h"
#include "istream-jsonstr.h"
struct jsonstr_istream {
/* The end '"' was found */
};
static int
unsigned int min_bytes)
{
if (ret <= 0) {
if (ret == -2) {
/* tiny parent buffer size - shouldn't happen */
return -2;
}
"EOF before trailing <\"> was seen");
}
return ret;
}
}
return -2;
return 1;
}
static int
unsigned char *dest,
unsigned int *src_size_r, unsigned int *dest_size_r)
{
switch (*src) {
case '"':
case '\\':
case '/':
break;
case 'b':
*dest = '\b';
break;
case 'f':
*dest = '\f';
break;
case 'n':
*dest = '\n';
break;
case 'r':
*dest = '\r';
break;
case 't':
*dest = '\t';
break;
case 'u': {
if (len < 5)
return 5;
return -1;
if (UTF16_VALID_LOW_SURROGATE(chr))
return -1;
/* if we encounter surrogate, we need another \\uxxxx */
if (UTF16_VALID_HIGH_SURROGATE(chr)) {
return 5+2+4;
return -1;
return -1;
if (!UTF16_VALID_LOW_SURROGATE(chr2))
return -1;
}
if (!uni_is_valid_ucs4(chr))
return -1;
return 0;
}
default:
return -1;
}
*src_size_r = 1;
*dest_size_r = 1;
return 0;
}
{
const unsigned char *data;
return -1;
}
if (ret <= 0)
return ret;
/* @UNSAFE */
extra = 0;
if (data[i] == '"') {
return -1;
}
break;
} else if (data[i] == '\\') {
if (i+1 == size) {
/* not enough input for \x */
extra = 1;
break;
}
/* UTF8 output is max. 6 chars */
return -2;
break;
}
i++;
/* invalid string */
"Invalid JSON string");
return -1;
} else if (ret2 > 0) {
/* we need to get more bytes, do not consume
escape slash */
i--;
break;
}
i += srcskip;
} else {
i++;
}
}
if (ret == 0) {
/* not enough input */
i_assert(i == 0);
if (ret <= 0)
return ret;
return i_stream_jsonstr_read(stream);
}
return ret;
}
{
i_stream_get_fd(input), 0);
}