Avoid stpncpy
It’s not worth the porting hassle, and as the glibc manual says, “this function is generally a poor choice for processing strings”. * admin/merge-gnulib (GNULIB_MODULES): Remove stpncpy. * exec/configure.ac: Do not check for stpncpy. * exec/exec.c (rpl_stpncpy, stpncpy): Remove this replacement. (exec_0): Properly clear buffer1. Use memcpy instead of stpncpy to add the trailing name. This code is clearly still suboptimal but efficiency is not that important here and I tried to minimize the change. * lib/gnulib.mk.in, m4/gnulib-comp.m4: Regenerate.
This commit is contained in:
@@ -45,7 +45,7 @@ GNULIB_MODULES='
|
|||||||
pathmax pipe2 pselect pthread_sigmask
|
pathmax pipe2 pselect pthread_sigmask
|
||||||
qcopy-acl readlink readlinkat regex
|
qcopy-acl readlink readlinkat regex
|
||||||
sig2str sigdescr_np socklen stat-time std-gnu11 stdbool stdckdint stddef stdio
|
sig2str sigdescr_np socklen stat-time std-gnu11 stdbool stdckdint stddef stdio
|
||||||
stpcpy stpncpy strnlen strnlen strtoimax symlink sys_stat sys_time
|
stpcpy strnlen strnlen strtoimax symlink sys_stat sys_time
|
||||||
tempname time-h time_r time_rz timegm timer-time timespec-add timespec-sub
|
tempname time-h time_r time_rz timegm timer-time timespec-add timespec-sub
|
||||||
update-copyright unlocked-io utimensat
|
update-copyright unlocked-io utimensat
|
||||||
vla warnings year2038
|
vla warnings year2038
|
||||||
|
|||||||
@@ -62,8 +62,8 @@ AC_TYPE_SSIZE_T
|
|||||||
AC_TYPE_PID_T
|
AC_TYPE_PID_T
|
||||||
|
|
||||||
AC_HEADER_STDBOOL
|
AC_HEADER_STDBOOL
|
||||||
AC_CHECK_FUNCS([getpagesize stpcpy stpncpy])
|
AC_CHECK_FUNCS([getpagesize stpcpy])
|
||||||
AC_CHECK_DECLS([stpcpy, stpncpy])
|
AC_CHECK_DECLS([stpcpy])
|
||||||
AC_CHECK_FUNC([process_vm_readv],
|
AC_CHECK_FUNC([process_vm_readv],
|
||||||
[AC_CHECK_FUNC([process_vm_writev],
|
[AC_CHECK_FUNC([process_vm_writev],
|
||||||
[AC_CHECK_DECL([process_vm_readv],
|
[AC_CHECK_DECL([process_vm_readv],
|
||||||
|
|||||||
77
exec/exec.c
77
exec/exec.c
@@ -66,74 +66,6 @@ rpl_stpcpy (char *dest, const char *src)
|
|||||||
#define stpcpy rpl_stpcpy
|
#define stpcpy rpl_stpcpy
|
||||||
#endif /* !defined HAVE_STPCPY || !defined HAVE_DECL_STPCPY */
|
#endif /* !defined HAVE_STPCPY || !defined HAVE_DECL_STPCPY */
|
||||||
|
|
||||||
#if !defined HAVE_STPNCPY || !defined HAVE_DECL_STPNCPY
|
|
||||||
|
|
||||||
/* Copy no more than N bytes of SRC to DST, returning a pointer past
|
|
||||||
the last non-NUL byte written into DST. */
|
|
||||||
|
|
||||||
static char *
|
|
||||||
rpl_stpncpy (char *dest, const char *src, size_t n)
|
|
||||||
{
|
|
||||||
char c, *s;
|
|
||||||
size_t n4;
|
|
||||||
|
|
||||||
s = dest;
|
|
||||||
|
|
||||||
if (n >= 4)
|
|
||||||
{
|
|
||||||
n4 = n >> 2;
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
c = *src++;
|
|
||||||
*dest++ = c;
|
|
||||||
if (c == '\0')
|
|
||||||
break;
|
|
||||||
c = *src++;
|
|
||||||
*dest++ = c;
|
|
||||||
if (c == '\0')
|
|
||||||
break;
|
|
||||||
c = *src++;
|
|
||||||
*dest++ = c;
|
|
||||||
if (c == '\0')
|
|
||||||
break;
|
|
||||||
c = *src++;
|
|
||||||
*dest++ = c;
|
|
||||||
if (c == '\0')
|
|
||||||
break;
|
|
||||||
if (--n4 == 0)
|
|
||||||
goto last_chars;
|
|
||||||
}
|
|
||||||
n -= dest - s;
|
|
||||||
goto zero_fill;
|
|
||||||
}
|
|
||||||
|
|
||||||
last_chars:
|
|
||||||
n &= 3;
|
|
||||||
if (n == 0)
|
|
||||||
return dest;
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
c = *src++;
|
|
||||||
--n;
|
|
||||||
*dest++ = c;
|
|
||||||
if (c == '\0')
|
|
||||||
break;
|
|
||||||
if (n == 0)
|
|
||||||
return dest;
|
|
||||||
}
|
|
||||||
|
|
||||||
zero_fill:
|
|
||||||
while (n-- > 0)
|
|
||||||
dest[n] = '\0';
|
|
||||||
|
|
||||||
return dest - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define stpncpy rpl_stpncpy
|
|
||||||
#endif /* !defined HAVE_STPNCPY || !defined HAVE_DECL_STPNCPY */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Executable reading functions.
|
/* Executable reading functions.
|
||||||
@@ -1005,13 +937,14 @@ exec_0 (char *name, struct exec_tracee *tracee,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* If name is not absolute, then make it relative to TRACEE's
|
/* If name is not absolute, then make it relative to TRACEE's
|
||||||
cwd. Use stpcpy, as sprintf is not reentrant. */
|
cwd. Do not use sprintf at it is not reentrant and it
|
||||||
|
mishandles results longer than INT_MAX. */
|
||||||
|
|
||||||
if (name[0] && name[0] != '/')
|
if (name[0] && name[0] != '/')
|
||||||
{
|
{
|
||||||
/* Clear `buffer'. */
|
/* Clear both buffers. */
|
||||||
memset (buffer, 0, sizeof buffer);
|
memset (buffer, 0, sizeof buffer);
|
||||||
memset (buffer1, 0, sizeof buffer);
|
memset (buffer1, 0, sizeof buffer1);
|
||||||
|
|
||||||
/* Copy over /proc, the PID, and /cwd/. */
|
/* Copy over /proc, the PID, and /cwd/. */
|
||||||
rewrite = stpcpy (buffer, "/proc/");
|
rewrite = stpcpy (buffer, "/proc/");
|
||||||
@@ -1042,7 +975,7 @@ exec_0 (char *name, struct exec_tracee *tracee,
|
|||||||
|
|
||||||
rewrite = buffer1 + link_size;
|
rewrite = buffer1 + link_size;
|
||||||
remaining = buffer1 + sizeof buffer1 - rewrite - 1;
|
remaining = buffer1 + sizeof buffer1 - rewrite - 1;
|
||||||
rewrite = stpncpy (rewrite, name, remaining);
|
memcpy (rewrite, name, strnlen (name, remaining));
|
||||||
|
|
||||||
/* Replace name with buffer1. */
|
/* Replace name with buffer1. */
|
||||||
#ifndef REENTRANT
|
#ifndef REENTRANT
|
||||||
|
|||||||
@@ -157,7 +157,6 @@
|
|||||||
# stddef \
|
# stddef \
|
||||||
# stdio \
|
# stdio \
|
||||||
# stpcpy \
|
# stpcpy \
|
||||||
# stpncpy \
|
|
||||||
# strnlen \
|
# strnlen \
|
||||||
# strtoimax \
|
# strtoimax \
|
||||||
# symlink \
|
# symlink \
|
||||||
@@ -336,7 +335,6 @@ GL_COND_OBJ_SIGDESCR_NP_CONDITION = @GL_COND_OBJ_SIGDESCR_NP_CONDITION@
|
|||||||
GL_COND_OBJ_STDIO_READ_CONDITION = @GL_COND_OBJ_STDIO_READ_CONDITION@
|
GL_COND_OBJ_STDIO_READ_CONDITION = @GL_COND_OBJ_STDIO_READ_CONDITION@
|
||||||
GL_COND_OBJ_STDIO_WRITE_CONDITION = @GL_COND_OBJ_STDIO_WRITE_CONDITION@
|
GL_COND_OBJ_STDIO_WRITE_CONDITION = @GL_COND_OBJ_STDIO_WRITE_CONDITION@
|
||||||
GL_COND_OBJ_STPCPY_CONDITION = @GL_COND_OBJ_STPCPY_CONDITION@
|
GL_COND_OBJ_STPCPY_CONDITION = @GL_COND_OBJ_STPCPY_CONDITION@
|
||||||
GL_COND_OBJ_STPNCPY_CONDITION = @GL_COND_OBJ_STPNCPY_CONDITION@
|
|
||||||
GL_COND_OBJ_STRNLEN_CONDITION = @GL_COND_OBJ_STRNLEN_CONDITION@
|
GL_COND_OBJ_STRNLEN_CONDITION = @GL_COND_OBJ_STRNLEN_CONDITION@
|
||||||
GL_COND_OBJ_STRTOIMAX_CONDITION = @GL_COND_OBJ_STRTOIMAX_CONDITION@
|
GL_COND_OBJ_STRTOIMAX_CONDITION = @GL_COND_OBJ_STRTOIMAX_CONDITION@
|
||||||
GL_COND_OBJ_STRTOLL_CONDITION = @GL_COND_OBJ_STRTOLL_CONDITION@
|
GL_COND_OBJ_STRTOLL_CONDITION = @GL_COND_OBJ_STRTOLL_CONDITION@
|
||||||
@@ -3454,16 +3452,6 @@ endif
|
|||||||
endif
|
endif
|
||||||
## end gnulib module stpcpy
|
## end gnulib module stpcpy
|
||||||
|
|
||||||
## begin gnulib module stpncpy
|
|
||||||
ifeq (,$(OMIT_GNULIB_MODULE_stpncpy))
|
|
||||||
|
|
||||||
ifneq (,$(GL_COND_OBJ_STPNCPY_CONDITION))
|
|
||||||
libgnu_a_SOURCES += stpncpy.c
|
|
||||||
endif
|
|
||||||
|
|
||||||
endif
|
|
||||||
## end gnulib module stpncpy
|
|
||||||
|
|
||||||
## begin gnulib module string
|
## begin gnulib module string
|
||||||
ifeq (,$(OMIT_GNULIB_MODULE_string))
|
ifeq (,$(OMIT_GNULIB_MODULE_string))
|
||||||
|
|
||||||
|
|||||||
@@ -1,92 +0,0 @@
|
|||||||
/* Copyright (C) 1993, 1995-1997, 2002-2003, 2005-2007, 2009-2023 Free Software
|
|
||||||
* Foundation, Inc.
|
|
||||||
|
|
||||||
NOTE: The canonical source of this file is maintained with the GNU C Library.
|
|
||||||
Bugs can be reported to bug-glibc@gnu.org.
|
|
||||||
|
|
||||||
This file is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as
|
|
||||||
published by the Free Software Foundation; either version 2.1 of the
|
|
||||||
License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This file is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
|
||||||
|
|
||||||
/* This is almost copied from strncpy.c, written by Torbjorn Granlund. */
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
|
|
||||||
/* Specification. */
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#ifndef weak_alias
|
|
||||||
# define __stpncpy stpncpy
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Copy no more than N bytes of SRC to DST, returning a pointer past the
|
|
||||||
last non-NUL byte written into DST. */
|
|
||||||
char *
|
|
||||||
(__stpncpy) (char *dest, const char *src, size_t n)
|
|
||||||
{
|
|
||||||
char c;
|
|
||||||
char *s = dest;
|
|
||||||
|
|
||||||
if (n >= 4)
|
|
||||||
{
|
|
||||||
size_t n4 = n >> 2;
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
c = *src++;
|
|
||||||
*dest++ = c;
|
|
||||||
if (c == '\0')
|
|
||||||
break;
|
|
||||||
c = *src++;
|
|
||||||
*dest++ = c;
|
|
||||||
if (c == '\0')
|
|
||||||
break;
|
|
||||||
c = *src++;
|
|
||||||
*dest++ = c;
|
|
||||||
if (c == '\0')
|
|
||||||
break;
|
|
||||||
c = *src++;
|
|
||||||
*dest++ = c;
|
|
||||||
if (c == '\0')
|
|
||||||
break;
|
|
||||||
if (--n4 == 0)
|
|
||||||
goto last_chars;
|
|
||||||
}
|
|
||||||
n -= dest - s;
|
|
||||||
goto zero_fill;
|
|
||||||
}
|
|
||||||
|
|
||||||
last_chars:
|
|
||||||
n &= 3;
|
|
||||||
if (n == 0)
|
|
||||||
return dest;
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
c = *src++;
|
|
||||||
--n;
|
|
||||||
*dest++ = c;
|
|
||||||
if (c == '\0')
|
|
||||||
break;
|
|
||||||
if (n == 0)
|
|
||||||
return dest;
|
|
||||||
}
|
|
||||||
|
|
||||||
zero_fill:
|
|
||||||
while (n-- > 0)
|
|
||||||
dest[n] = '\0';
|
|
||||||
|
|
||||||
return dest - 1;
|
|
||||||
}
|
|
||||||
#ifdef weak_alias
|
|
||||||
weak_alias (__stpncpy, stpncpy)
|
|
||||||
#endif
|
|
||||||
@@ -181,7 +181,6 @@ AC_DEFUN([gl_EARLY],
|
|||||||
gl_STDIO_H_EARLY
|
gl_STDIO_H_EARLY
|
||||||
# Code from module stdlib:
|
# Code from module stdlib:
|
||||||
# Code from module stpcpy:
|
# Code from module stpcpy:
|
||||||
# Code from module stpncpy:
|
|
||||||
# Code from module string:
|
# Code from module string:
|
||||||
# Code from module strnlen:
|
# Code from module strnlen:
|
||||||
# Code from module strtoimax:
|
# Code from module strtoimax:
|
||||||
@@ -567,13 +566,6 @@ AC_DEFUN([gl_INIT],
|
|||||||
gl_PREREQ_STPCPY
|
gl_PREREQ_STPCPY
|
||||||
])
|
])
|
||||||
gl_STRING_MODULE_INDICATOR([stpcpy])
|
gl_STRING_MODULE_INDICATOR([stpcpy])
|
||||||
gl_FUNC_STPNCPY
|
|
||||||
gl_CONDITIONAL([GL_COND_OBJ_STPNCPY],
|
|
||||||
[test $HAVE_STPNCPY = 0 || test $REPLACE_STPNCPY = 1])
|
|
||||||
AM_COND_IF([GL_COND_OBJ_STPNCPY], [
|
|
||||||
gl_PREREQ_STPNCPY
|
|
||||||
])
|
|
||||||
gl_STRING_MODULE_INDICATOR([stpncpy])
|
|
||||||
gl_STRING_H
|
gl_STRING_H
|
||||||
gl_STRING_H_REQUIRE_DEFAULTS
|
gl_STRING_H_REQUIRE_DEFAULTS
|
||||||
AC_PROG_MKDIR_P
|
AC_PROG_MKDIR_P
|
||||||
@@ -1422,7 +1414,6 @@ AC_DEFUN([gl_FILE_LIST], [
|
|||||||
lib/stdio.in.h
|
lib/stdio.in.h
|
||||||
lib/stdlib.in.h
|
lib/stdlib.in.h
|
||||||
lib/stpcpy.c
|
lib/stpcpy.c
|
||||||
lib/stpncpy.c
|
|
||||||
lib/str-two-way.h
|
lib/str-two-way.h
|
||||||
lib/strftime.h
|
lib/strftime.h
|
||||||
lib/string.in.h
|
lib/string.in.h
|
||||||
@@ -1569,7 +1560,6 @@ AC_DEFUN([gl_FILE_LIST], [
|
|||||||
m4/stdio_h.m4
|
m4/stdio_h.m4
|
||||||
m4/stdlib_h.m4
|
m4/stdlib_h.m4
|
||||||
m4/stpcpy.m4
|
m4/stpcpy.m4
|
||||||
m4/stpncpy.m4
|
|
||||||
m4/string_h.m4
|
m4/string_h.m4
|
||||||
m4/strnlen.m4
|
m4/strnlen.m4
|
||||||
m4/strtoimax.m4
|
m4/strtoimax.m4
|
||||||
|
|||||||
108
m4/stpncpy.m4
108
m4/stpncpy.m4
@@ -1,108 +0,0 @@
|
|||||||
# stpncpy.m4 serial 22
|
|
||||||
dnl Copyright (C) 2002-2003, 2005-2007, 2009-2023 Free Software Foundation,
|
|
||||||
dnl Inc.
|
|
||||||
dnl This file is free software; the Free Software Foundation
|
|
||||||
dnl gives unlimited permission to copy and/or distribute it,
|
|
||||||
dnl with or without modifications, as long as this notice is preserved.
|
|
||||||
|
|
||||||
AC_DEFUN([gl_FUNC_STPNCPY],
|
|
||||||
[
|
|
||||||
AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
|
|
||||||
|
|
||||||
dnl Persuade glibc <string.h> to declare stpncpy().
|
|
||||||
AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])
|
|
||||||
|
|
||||||
dnl The stpncpy() declaration in lib/string.in.h uses 'restrict'.
|
|
||||||
AC_REQUIRE([AC_C_RESTRICT])
|
|
||||||
|
|
||||||
AC_REQUIRE([gl_STRING_H_DEFAULTS])
|
|
||||||
|
|
||||||
dnl Both glibc and AIX (4.3.3, 5.1) have an stpncpy() function
|
|
||||||
dnl declared in <string.h>. Its side effects are the same as those
|
|
||||||
dnl of strncpy():
|
|
||||||
dnl stpncpy (dest, src, n)
|
|
||||||
dnl overwrites dest[0..n-1], min(strlen(src),n) bytes coming from src,
|
|
||||||
dnl and the remaining bytes being NULs. However, the return value is
|
|
||||||
dnl in glibc: dest + min(strlen(src),n)
|
|
||||||
dnl in AIX: dest + max(0,n-1)
|
|
||||||
dnl Only the glibc return value is useful in practice.
|
|
||||||
|
|
||||||
AC_CHECK_DECLS_ONCE([stpncpy])
|
|
||||||
gl_CHECK_FUNCS_ANDROID([stpncpy], [[#include <string.h>]])
|
|
||||||
if test $ac_cv_func_stpncpy = yes; then
|
|
||||||
AC_CACHE_CHECK([for working stpncpy], [gl_cv_func_stpncpy], [
|
|
||||||
AC_RUN_IFELSE(
|
|
||||||
[AC_LANG_SOURCE([[
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h> /* for strcpy */
|
|
||||||
/* The stpncpy prototype is missing in <string.h> on AIX 4. */
|
|
||||||
#if !HAVE_DECL_STPNCPY
|
|
||||||
extern
|
|
||||||
# ifdef __cplusplus
|
|
||||||
"C"
|
|
||||||
# endif
|
|
||||||
char *stpncpy (char *dest, const char *src, size_t n);
|
|
||||||
#endif
|
|
||||||
int main ()
|
|
||||||
{
|
|
||||||
int result = 0;
|
|
||||||
const char *src = "Hello";
|
|
||||||
char dest[10];
|
|
||||||
/* AIX 4.3.3 and AIX 5.1 stpncpy() returns dest+1 here. */
|
|
||||||
{
|
|
||||||
strcpy (dest, "\377\377\377\377\377\377");
|
|
||||||
if (stpncpy (dest, src, 2) != dest + 2)
|
|
||||||
result |= 1;
|
|
||||||
}
|
|
||||||
/* AIX 4.3.3 and AIX 5.1 stpncpy() returns dest+4 here. */
|
|
||||||
{
|
|
||||||
strcpy (dest, "\377\377\377\377\377\377");
|
|
||||||
if (stpncpy (dest, src, 5) != dest + 5)
|
|
||||||
result |= 2;
|
|
||||||
}
|
|
||||||
/* AIX 4.3.3 and AIX 5.1 stpncpy() returns dest+6 here. */
|
|
||||||
{
|
|
||||||
strcpy (dest, "\377\377\377\377\377\377");
|
|
||||||
if (stpncpy (dest, src, 7) != dest + 5)
|
|
||||||
result |= 4;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
]])],
|
|
||||||
[gl_cv_func_stpncpy=yes],
|
|
||||||
[gl_cv_func_stpncpy=no],
|
|
||||||
[dnl Guess yes on glibc systems and musl systems.
|
|
||||||
AC_EGREP_CPP([Thanks for using GNU], [
|
|
||||||
#include <features.h>
|
|
||||||
#ifdef __GNU_LIBRARY__
|
|
||||||
Thanks for using GNU
|
|
||||||
#endif
|
|
||||||
], [gl_cv_func_stpncpy="guessing yes"],
|
|
||||||
[case "$host_os" in
|
|
||||||
*-musl* | midipix*) gl_cv_func_stpncpy="guessing yes" ;;
|
|
||||||
*) gl_cv_func_stpncpy="$gl_cross_guess_normal" ;;
|
|
||||||
esac
|
|
||||||
])
|
|
||||||
])
|
|
||||||
])
|
|
||||||
case "$gl_cv_func_stpncpy" in
|
|
||||||
*yes)
|
|
||||||
AC_DEFINE([HAVE_STPNCPY], [1],
|
|
||||||
[Define if you have the stpncpy() function and it works.])
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
REPLACE_STPNCPY=1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
else
|
|
||||||
HAVE_STPNCPY=0
|
|
||||||
case "$gl_cv_onwards_func_stpncpy" in
|
|
||||||
future*) REPLACE_STPNCPY=1 ;;
|
|
||||||
esac
|
|
||||||
fi
|
|
||||||
])
|
|
||||||
|
|
||||||
# Prerequisites of lib/stpncpy.c.
|
|
||||||
AC_DEFUN([gl_PREREQ_STPNCPY], [
|
|
||||||
:
|
|
||||||
])
|
|
||||||
Reference in New Issue
Block a user