Avoid use of non-portable strnlen() in pgstat_clip_activity().

The use of strnlen rather than strlen was just paranoia. Instead of
giving up on the paranoia, just implement the safeguard
differently. And add a comment explaining why we're careful.

Author: Andres Freund
Discussion: https://postgr.es/m/E1duOkJ-0001Mc-U5@gemulon.postgresql.org
This commit is contained in:
Andres Freund 2017-09-19 14:17:20 -07:00
parent 54b6cd589a
commit 71edbb6f66
2 changed files with 22 additions and 5 deletions

View File

@ -6288,10 +6288,24 @@ pgstat_db_requested(Oid databaseid)
* freed.
*/
char *
pgstat_clip_activity(const char *activity)
pgstat_clip_activity(const char *raw_activity)
{
int rawlen = strnlen(activity, pgstat_track_activity_query_size - 1);
int cliplen;
char *activity;
int rawlen;
int cliplen;
/*
* Some callers, like pgstat_get_backend_current_activity(), do not
* guarantee that the buffer isn't concurrently modified. We try to take
* care that the buffer is always terminated by a NULL byte regardless,
* but let's still be paranoid about the string's length. In those cases
* the underlying buffer is guaranteed to be
* pgstat_track_activity_query_size large.
*/
activity = pnstrdup(raw_activity, pgstat_track_activity_query_size - 1);
/* now double-guaranteed to be NULL terminated */
rawlen = strlen(activity);
/*
* All supported server-encodings make it possible to determine the length
@ -6303,5 +6317,8 @@ pgstat_clip_activity(const char *activity)
*/
cliplen = pg_mbcliplen(activity, rawlen,
pgstat_track_activity_query_size - 1);
return pnstrdup(activity, cliplen);
activity[cliplen] = '\0';
return activity;
}

View File

@ -1199,7 +1199,7 @@ extern PgStat_BackendFunctionEntry *find_funcstat_entry(Oid func_id);
extern void pgstat_initstats(Relation rel);
extern char *pgstat_clip_activity(const char *activity);
extern char *pgstat_clip_activity(const char *raw_activity);
/* ----------
* pgstat_report_wait_start() -