summaryrefslogtreecommitdiff
path: root/src/interfaces
diff options
context:
space:
mode:
Diffstat (limited to 'src/interfaces')
-rw-r--r--src/interfaces/libpq/exports.txt1
-rw-r--r--src/interfaces/libpq/fe-misc.c19
-rw-r--r--src/interfaces/libpq/fe-print.c2
-rw-r--r--src/interfaces/libpq/fe-protocol3.c4
-rw-r--r--src/interfaces/libpq/libpq-fe.h3
5 files changed, 24 insertions, 5 deletions
diff --git a/src/interfaces/libpq/exports.txt b/src/interfaces/libpq/exports.txt
index a00701f2c5f..9ef99f6de12 100644
--- a/src/interfaces/libpq/exports.txt
+++ b/src/interfaces/libpq/exports.txt
@@ -184,3 +184,4 @@ PQexitPipelineMode 181
PQpipelineSync 182
PQpipelineStatus 183
PQtraceSetFlags 184
+PQmblenBounded 185
diff --git a/src/interfaces/libpq/fe-misc.c b/src/interfaces/libpq/fe-misc.c
index b347d7f8479..9a2a9702934 100644
--- a/src/interfaces/libpq/fe-misc.c
+++ b/src/interfaces/libpq/fe-misc.c
@@ -1180,8 +1180,13 @@ pqSocketPoll(int sock, int forRead, int forWrite, time_t end_time)
*/
/*
- * 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)
@@ -1190,7 +1195,17 @@ 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
diff --git a/src/interfaces/libpq/fe-print.c b/src/interfaces/libpq/fe-print.c
index 94219b1825b..fc7d84844e1 100644
--- a/src/interfaces/libpq/fe-print.c
+++ b/src/interfaces/libpq/fe-print.c
@@ -365,7 +365,7 @@ do_field(const PQprintOpt *po, const PGresult *res,
/* 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') ||
diff --git a/src/interfaces/libpq/fe-protocol3.c b/src/interfaces/libpq/fe-protocol3.c
index b45fb7e7059..2e833053487 100644
--- a/src/interfaces/libpq/fe-protocol3.c
+++ b/src/interfaces/libpq/fe-protocol3.c
@@ -1296,7 +1296,7 @@ reportErrorPosition(PQExpBuffer msg, const char *query, int loc, int encoding)
if (w <= 0)
w = 1;
scroffset += w;
- qoffset += pg_encoding_mblen(encoding, &wquery[qoffset]);
+ qoffset += PQmblenBounded(&wquery[qoffset], encoding);
}
else
{
@@ -1364,7 +1364,7 @@ reportErrorPosition(PQExpBuffer msg, const char *query, int loc, int encoding)
* 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]);
diff --git a/src/interfaces/libpq/libpq-fe.h b/src/interfaces/libpq/libpq-fe.h
index 227adde5a5e..845b4c04c9c 100644
--- a/src/interfaces/libpq/libpq-fe.h
+++ b/src/interfaces/libpq/libpq-fe.h
@@ -625,6 +625,9 @@ extern int PQlibVersion(void);
/* 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);