while (*query)
{
- int mblen = PQmblen(query, pset.encoding);
+ int mblen = PQmblenBounded(query, pset.encoding);
/*
* Note: we assume the encoding is a superset of ASCII, so that for
query++;
break;
}
- query += PQmblen(query, pset.encoding);
+ query += PQmblenBounded(query, pset.encoding);
}
}
else if (cnestlevel > 0)
*/
wordlen = 0;
while (isalpha((unsigned char) query[wordlen]))
- wordlen += PQmblen(&query[wordlen], pset.encoding);
+ wordlen += PQmblenBounded(&query[wordlen], pset.encoding);
/*
* Transaction control commands. These should include every keyword that
wordlen = 0;
while (isalpha((unsigned char) query[wordlen]))
- wordlen += PQmblen(&query[wordlen], pset.encoding);
+ wordlen += PQmblenBounded(&query[wordlen], pset.encoding);
if (wordlen == 11 && pg_strncasecmp(query, "transaction", 11) == 0)
return true;
wordlen = 0;
while (isalpha((unsigned char) query[wordlen]))
- wordlen += PQmblen(&query[wordlen], pset.encoding);
+ wordlen += PQmblenBounded(&query[wordlen], pset.encoding);
if (wordlen == 8 && pg_strncasecmp(query, "database", 8) == 0)
return true;
wordlen = 0;
while (isalpha((unsigned char) query[wordlen]))
- wordlen += PQmblen(&query[wordlen], pset.encoding);
+ wordlen += PQmblenBounded(&query[wordlen], pset.encoding);
}
if (wordlen == 5 && pg_strncasecmp(query, "index", 5) == 0)
wordlen = 0;
while (isalpha((unsigned char) query[wordlen]))
- wordlen += PQmblen(&query[wordlen], pset.encoding);
+ wordlen += PQmblenBounded(&query[wordlen], pset.encoding);
if (wordlen == 12 && pg_strncasecmp(query, "concurrently", 12) == 0)
return true;
wordlen = 0;
while (isalpha((unsigned char) query[wordlen]))
- wordlen += PQmblen(&query[wordlen], pset.encoding);
+ wordlen += PQmblenBounded(&query[wordlen], pset.encoding);
/* ALTER SYSTEM isn't allowed in xacts */
if (wordlen == 6 && pg_strncasecmp(query, "system", 6) == 0)
wordlen = 0;
while (isalpha((unsigned char) query[wordlen]))
- wordlen += PQmblen(&query[wordlen], pset.encoding);
+ wordlen += PQmblenBounded(&query[wordlen], pset.encoding);
if (wordlen == 8 && pg_strncasecmp(query, "database", 8) == 0)
return true;
query = skip_white_space(query);
wordlen = 0;
while (isalpha((unsigned char) query[wordlen]))
- wordlen += PQmblen(&query[wordlen], pset.encoding);
+ wordlen += PQmblenBounded(&query[wordlen], pset.encoding);
/*
* REINDEX [ TABLE | INDEX ] CONCURRENTLY are not allowed in
wordlen = 0;
while (isalpha((unsigned char) query[wordlen]))
- wordlen += PQmblen(&query[wordlen], pset.encoding);
+ wordlen += PQmblenBounded(&query[wordlen], pset.encoding);
if (wordlen == 12 && pg_strncasecmp(query, "concurrently", 12) == 0)
return true;
wordlen = 0;
while (isalpha((unsigned char) query[wordlen]))
- wordlen += PQmblen(&query[wordlen], pset.encoding);
+ wordlen += PQmblenBounded(&query[wordlen], pset.encoding);
if (wordlen == 3 && pg_strncasecmp(query, "all", 3) == 0)
return true;
*/
wordlen = 0;
while (isalpha((unsigned char) query[wordlen]))
- wordlen += PQmblen(&query[wordlen], pset.encoding);
+ wordlen += PQmblenBounded(&query[wordlen], pset.encoding);
if (wordlen == 6 && pg_strncasecmp(query, "select", 6) == 0)
return true;
{
if (downcase && !inquotes)
*cp = pg_tolower((unsigned char) *cp);
- cp += PQmblen(cp, encoding);
+ cp += PQmblenBounded(cp, encoding);
}
}
}
/* okay, we have a quoted token, now scan for the closer */
char thisquote = *p++;
- for (; *p; p += PQmblen(p, encoding))
+ for (; *p; p += PQmblenBounded(p, encoding))
{
if (*p == escape && p[1] != '\0')
p++; /* process escaped anything */
else if (c == escape && src[1] != '\0')
src++; /* process escaped character */
- i = PQmblen(src, encoding);
+ i = PQmblenBounded(src, encoding);
while (i--)
*dst++ = *src++;
}
else if (strchr(entails_quote, c))
need_quotes = true;
- i = PQmblen(src, encoding);
+ i = PQmblenBounded(src, encoding);
while (i--)
*dst++ = *src++;
}
while (*pstr)
{
char_length++;
- pstr += PQmblen(pstr, pset.encoding);
+ pstr += PQmblenBounded(pstr, pset.encoding);
}
/* Free any prior result */
cp++;
}
else
- cp += PQmblen(cp, encoding);
+ cp += PQmblenBounded(cp, encoding);
}
*table = pnstrdup(spec, cp - spec);
*columns = cp;
ch = (ch * 16) + (*s - 'A') + 10;
else
{
- lex->token_terminator = s + pg_encoding_mblen(lex->input_encoding, s);
+ lex->token_terminator = s + pg_encoding_mblen_bounded(lex->input_encoding, s);
return JSON_UNICODE_ESCAPE_FORMAT;
}
}
default:
/* Not a valid string escape, so signal error. */
lex->token_start = s;
- lex->token_terminator = s + pg_encoding_mblen(lex->input_encoding, s);
+ lex->token_terminator = s + pg_encoding_mblen_bounded(lex->input_encoding, s);
return JSON_ESCAPING_INVALID;
}
}
* shown it's not a performance win.
*/
lex->token_start = s;
- lex->token_terminator = s + pg_encoding_mblen(lex->input_encoding, s);
+ lex->token_terminator = s + pg_encoding_mblen_bounded(lex->input_encoding, s);
return JSON_ESCAPING_INVALID;
}
/*
* Returns the byte length of a multibyte character.
+ *
+ * Caution: when dealing with text that is not certainly valid in the
+ * specified encoding, the result may exceed the actual remaining
+ * string length. Callers that are not prepared to deal with that
+ * should use pg_encoding_mblen_bounded() instead.
*/
int
pg_encoding_mblen(int encoding, const char *mbstr)
pg_wchar_table[PG_SQL_ASCII].mblen((const unsigned char *) mbstr));
}
+/*
+ * Returns the byte length of a multibyte character; but not more than
+ * the distance to end of string.
+ */
+int
+pg_encoding_mblen_bounded(int encoding, const char *mbstr)
+{
+ return strnlen(mbstr, pg_encoding_mblen(encoding, mbstr));
+}
+
/*
* Returns the display length of a multibyte character.
*/
curr_width += char_width;
str += PQmblen((char *) str, encoding);
+
+ if (str > end) /* Don't overrun invalid string */
+ str = end;
}
*target_width = curr_width;
appendPQExpBufferChar(curbuf, '\\');
else if (ch == '[' && cp[1] == ']')
appendPQExpBufferChar(curbuf, '\\');
- i = PQmblen(cp, encoding);
- while (i-- && *cp)
- {
- appendPQExpBufferChar(curbuf, *cp);
- cp++;
- }
+ i = PQmblenBounded(cp, encoding);
+ while (i--)
+ appendPQExpBufferChar(curbuf, *cp++);
}
}
appendPQExpBufferStr(curbuf, ")$");
* earlier in this file are also available from libpgcommon.
*/
extern int pg_encoding_mblen(int encoding, const char *mbstr);
+extern int pg_encoding_mblen_bounded(int encoding, const char *mbstr);
extern int pg_encoding_dsplen(int encoding, const char *mbstr);
extern int pg_encoding_verifymbchar(int encoding, const char *mbstr, int len);
extern int pg_encoding_verifymbstr(int encoding, const char *mbstr, int len);
PQpipelineSync 182
PQpipelineStatus 183
PQtraceSetFlags 184
+PQmblenBounded 185
*/
/*
- * returns the byte length of the character beginning at s, using the
+ * Returns the byte length of the character beginning at s, using the
* specified encoding.
+ *
+ * Caution: when dealing with text that is not certainly valid in the
+ * specified encoding, the result may exceed the actual remaining
+ * string length. Callers that are not prepared to deal with that
+ * should use PQmblenBounded() instead.
*/
int
PQmblen(const char *s, int encoding)
}
/*
- * returns the display length of the character beginning at s, using the
+ * Returns the byte length of the character beginning at s, using the
+ * specified encoding; but not more than the distance to end of string.
+ */
+int
+PQmblenBounded(const char *s, int encoding)
+{
+ return strnlen(s, pg_encoding_mblen(encoding, s));
+}
+
+/*
+ * Returns the display length of the character beginning at s, using the
* specified encoding.
*/
int
/* Detect whether field contains non-numeric data */
char ch = '0';
- for (p = pval; *p; p += PQmblen(p, res->client_encoding))
+ for (p = pval; *p; p += PQmblenBounded(p, res->client_encoding))
{
ch = *p;
if (!((ch >= '0' && ch <= '9') ||
if (w <= 0)
w = 1;
scroffset += w;
- qoffset += pg_encoding_mblen(encoding, &wquery[qoffset]);
+ qoffset += PQmblenBounded(&wquery[qoffset], encoding);
}
else
{
* width.
*/
scroffset = 0;
- for (; i < msg->len; i += pg_encoding_mblen(encoding, &msg->data[i]))
+ for (; i < msg->len; i += PQmblenBounded(&msg->data[i], encoding))
{
int w = pg_encoding_dsplen(encoding, &msg->data[i]);
/* Determine length of multibyte encoded char at *s */
extern int PQmblen(const char *s, int encoding);
+/* Same, but not more than the distance to the end of string s */
+extern int PQmblenBounded(const char *s, int encoding);
+
/* Determine display length of multibyte encoded char at *s */
extern int PQdsplen(const char *s, int encoding);