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:
parent
f3868cb9d1
commit
5315e6e8d7
7 changed files with 8 additions and 297 deletions
|
@ -45,7 +45,7 @@ GNULIB_MODULES='
|
|||
pathmax pipe2 pselect pthread_sigmask
|
||||
qcopy-acl readlink readlinkat regex
|
||||
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
|
||||
update-copyright unlocked-io utimensat
|
||||
vla warnings year2038
|
||||
|
|
|
@ -62,8 +62,8 @@ AC_TYPE_SSIZE_T
|
|||
AC_TYPE_PID_T
|
||||
|
||||
AC_HEADER_STDBOOL
|
||||
AC_CHECK_FUNCS([getpagesize stpcpy stpncpy])
|
||||
AC_CHECK_DECLS([stpcpy, stpncpy])
|
||||
AC_CHECK_FUNCS([getpagesize stpcpy])
|
||||
AC_CHECK_DECLS([stpcpy])
|
||||
AC_CHECK_FUNC([process_vm_readv],
|
||||
[AC_CHECK_FUNC([process_vm_writev],
|
||||
[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
|
||||
#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.
|
||||
|
@ -1005,13 +937,14 @@ exec_0 (char *name, struct exec_tracee *tracee,
|
|||
else
|
||||
{
|
||||
/* 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] != '/')
|
||||
{
|
||||
/* Clear `buffer'. */
|
||||
/* Clear both buffers. */
|
||||
memset (buffer, 0, sizeof buffer);
|
||||
memset (buffer1, 0, sizeof buffer);
|
||||
memset (buffer1, 0, sizeof buffer1);
|
||||
|
||||
/* Copy over /proc, the PID, and /cwd/. */
|
||||
rewrite = stpcpy (buffer, "/proc/");
|
||||
|
@ -1042,7 +975,7 @@ exec_0 (char *name, struct exec_tracee *tracee,
|
|||
|
||||
rewrite = buffer1 + link_size;
|
||||
remaining = buffer1 + sizeof buffer1 - rewrite - 1;
|
||||
rewrite = stpncpy (rewrite, name, remaining);
|
||||
memcpy (rewrite, name, strnlen (name, remaining));
|
||||
|
||||
/* Replace name with buffer1. */
|
||||
#ifndef REENTRANT
|
||||
|
|
|
@ -157,7 +157,6 @@
|
|||
# stddef \
|
||||
# stdio \
|
||||
# stpcpy \
|
||||
# stpncpy \
|
||||
# strnlen \
|
||||
# strtoimax \
|
||||
# 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_WRITE_CONDITION = @GL_COND_OBJ_STDIO_WRITE_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_STRTOIMAX_CONDITION = @GL_COND_OBJ_STRTOIMAX_CONDITION@
|
||||
GL_COND_OBJ_STRTOLL_CONDITION = @GL_COND_OBJ_STRTOLL_CONDITION@
|
||||
|
@ -3454,16 +3452,6 @@ endif
|
|||
endif
|
||||
## 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
|
||||
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
|
||||
# Code from module stdlib:
|
||||
# Code from module stpcpy:
|
||||
# Code from module stpncpy:
|
||||
# Code from module string:
|
||||
# Code from module strnlen:
|
||||
# Code from module strtoimax:
|
||||
|
@ -567,13 +566,6 @@ AC_DEFUN([gl_INIT],
|
|||
gl_PREREQ_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_REQUIRE_DEFAULTS
|
||||
AC_PROG_MKDIR_P
|
||||
|
@ -1422,7 +1414,6 @@ AC_DEFUN([gl_FILE_LIST], [
|
|||
lib/stdio.in.h
|
||||
lib/stdlib.in.h
|
||||
lib/stpcpy.c
|
||||
lib/stpncpy.c
|
||||
lib/str-two-way.h
|
||||
lib/strftime.h
|
||||
lib/string.in.h
|
||||
|
@ -1569,7 +1560,6 @@ AC_DEFUN([gl_FILE_LIST], [
|
|||
m4/stdio_h.m4
|
||||
m4/stdlib_h.m4
|
||||
m4/stpcpy.m4
|
||||
m4/stpncpy.m4
|
||||
m4/string_h.m4
|
||||
m4/strnlen.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], [
|
||||
:
|
||||
])
|
Loading…
Add table
Reference in a new issue