Offer pnstrdup to frontend code

We already had it on the backend.  Frontend can also use it now.

Discussion: https://postgr.es/m/20191204144021.GA17976@alvherre.pgsql
This commit is contained in:
Alvaro Herrera 2019-12-04 19:36:06 -03:00
parent b1abfec825
commit 0b9466fce2
6 changed files with 36 additions and 35 deletions

View File

@ -114,8 +114,7 @@ split_path(const char *path, char **dir, char **fname)
/* directory path */ /* directory path */
if (sep != NULL) if (sep != NULL)
{ {
*dir = pg_strdup(path); *dir = pnstrdup(path, sep - path);
(*dir)[(sep - path) + 1] = '\0'; /* no strndup */
*fname = pg_strdup(sep + 1); *fname = pg_strdup(sep + 1);
} }
/* local directory */ /* local directory */

View File

@ -270,13 +270,10 @@ get_prompt(promptStatus_t status, ConditionalStack cstack)
/* execute command */ /* execute command */
case '`': case '`':
{ {
FILE *fd; int cmdend = strcspn(p + 1, "`");
char *file = pg_strdup(p + 1); char *file = pnstrdup(p + 1, cmdend);
int cmdend; FILE *fd = popen(file, "r");
cmdend = strcspn(file, "`");
file[cmdend] = '\0';
fd = popen(file, "r");
if (fd) if (fd)
{ {
if (fgets(buf, sizeof(buf), fd) == NULL) if (fgets(buf, sizeof(buf), fd) == NULL)
@ -295,13 +292,10 @@ get_prompt(promptStatus_t status, ConditionalStack cstack)
/* interpolate variable */ /* interpolate variable */
case ':': case ':':
{ {
char *name; int nameend = strcspn(p + 1, ":");
char *name = pnstrdup(p + 1, nameend);
const char *val; const char *val;
int nameend;
name = pg_strdup(p + 1);
nameend = strcspn(name, ":");
name[nameend] = '\0';
val = GetVariable(pset.vars, name); val = GetVariable(pset.vars, name);
if (val) if (val)
strlcpy(buf, val, sizeof(buf)); strlcpy(buf, val, sizeof(buf));

View File

@ -353,8 +353,7 @@ splitTableColumnsSpec(const char *spec, int encoding,
else else
cp += PQmblen(cp, encoding); cp += PQmblen(cp, encoding);
} }
*table = pg_strdup(spec); *table = pnstrdup(spec, cp - spec);
(*table)[cp - spec] = '\0'; /* no strndup */
*columns = cp; *columns = cp;
} }

View File

@ -142,6 +142,33 @@ pstrdup(const char *in)
return pg_strdup(in); return pg_strdup(in);
} }
char *
pnstrdup(const char *in, Size size)
{
char *tmp;
int len;
if (!in)
{
fprintf(stderr,
_("cannot duplicate null pointer (internal error)\n"));
exit(EXIT_FAILURE);
}
len = strnlen(in, size);
tmp = malloc(len + 1);
if (tmp == NULL)
{
fprintf(stderr, _("out of memory\n"));
exit(EXIT_FAILURE);
}
memcpy(tmp, in, len);
tmp[len] = '\0';
return tmp;
}
void * void *
repalloc(void *pointer, Size size) repalloc(void *pointer, Size size)
{ {

View File

@ -31,6 +31,7 @@ extern void pg_free(void *pointer);
/* Equivalent functions, deliberately named the same as backend functions */ /* Equivalent functions, deliberately named the same as backend functions */
extern char *pstrdup(const char *in); extern char *pstrdup(const char *in);
extern char *pnstrdup(const char *in, Size size);
extern void *palloc(Size size); extern void *palloc(Size size);
extern void *palloc0(Size size); extern void *palloc0(Size size);
extern void *palloc_extended(Size size, int flags); extern void *palloc_extended(Size size, int flags);

View File

@ -175,25 +175,6 @@ deccopy(decimal *src, decimal *target)
memcpy(target, src, sizeof(decimal)); memcpy(target, src, sizeof(decimal));
} }
static char *
ecpg_strndup(const char *str, size_t len)
{
size_t real_len = strlen(str);
int use_len = (int) ((real_len > len) ? len : real_len);
char *new = malloc(use_len + 1);
if (new)
{
memcpy(new, str, use_len);
new[use_len] = '\0';
}
else
errno = ENOMEM;
return new;
}
int int
deccvasc(const char *cp, int len, decimal *np) deccvasc(const char *cp, int len, decimal *np)
{ {
@ -205,7 +186,7 @@ deccvasc(const char *cp, int len, decimal *np)
if (risnull(CSTRINGTYPE, cp)) if (risnull(CSTRINGTYPE, cp))
return 0; return 0;
str = ecpg_strndup(cp, len); /* decimal_in always converts the complete str = pnstrdup(cp, len); /* decimal_in always converts the complete
* string */ * string */
if (!str) if (!str)
ret = ECPG_INFORMIX_NUM_UNDERFLOW; ret = ECPG_INFORMIX_NUM_UNDERFLOW;