shadow/libmisc/date_to_str.c

57 lines
1.9 KiB
C
Raw Normal View History

/*
* Copyright (c) 2021, Alejandro Colomar <alx.manpages@gmail.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <string.h>
#include <time.h>
#ident "$Id$"
#include "prototypes.h"
void
date_to_str(size_t size, char buf[size], long date)
{
time_t t;
const struct tm *tm;
t = date;
Use strlcpy(3) instead of its pattern - Since strncpy(3) is not designed to write strings, but rather (null-padded) character sequences (a.k.a. unterminated strings), we had to manually append a '\0'. strlcpy(3) creates strings, so they are always terminated. This removes dependencies between lines, and also removes chances of accidents. - Repurposing strncpy(3) to create strings requires calculating the location of the terminating null byte, which involves a '-1' calculation. This is a source of off-by-one bugs. The new code has no '-1' calculations, so there's almost-zero chance of these bugs. - strlcpy(3) doesn't padd with null bytes. Padding is relevant when writing fixed-width buffers to binary files, when interfacing certain APIs (I believe utmpx requires null padding at lease in some systems), or when sending them to other processes or through the network. This is not the case, so padding is effectively ignored. - strlcpy(3) requires that the input string is really a string; otherwise it crashes (SIGSEGV). Let's check if the input strings are really strings: - lib/fields.c: - 'cp' was assigned from 'newft', and 'newft' comes from fgets(3). - lib/gshadow.c: - strlen(string) is calculated a few lines above. - libmisc/console.c: - 'cons' comes from getdef_str, which is a bit cryptic, but seems to generate strings, I guess.1 - libmisc/date_to_str.c: - It receives a string literal. :) - libmisc/utmp.c: - 'tname' comes from ttyname(3), which returns a string. - src/su.c: - 'tmp_name' has been passed to strcmp(3) a few lines above. Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-16 08:43:53 +05:30
if (date < 0) {
(void) strlcpy(buf, "never", size);
return;
Use strlcpy(3) instead of its pattern - Since strncpy(3) is not designed to write strings, but rather (null-padded) character sequences (a.k.a. unterminated strings), we had to manually append a '\0'. strlcpy(3) creates strings, so they are always terminated. This removes dependencies between lines, and also removes chances of accidents. - Repurposing strncpy(3) to create strings requires calculating the location of the terminating null byte, which involves a '-1' calculation. This is a source of off-by-one bugs. The new code has no '-1' calculations, so there's almost-zero chance of these bugs. - strlcpy(3) doesn't padd with null bytes. Padding is relevant when writing fixed-width buffers to binary files, when interfacing certain APIs (I believe utmpx requires null padding at lease in some systems), or when sending them to other processes or through the network. This is not the case, so padding is effectively ignored. - strlcpy(3) requires that the input string is really a string; otherwise it crashes (SIGSEGV). Let's check if the input strings are really strings: - lib/fields.c: - 'cp' was assigned from 'newft', and 'newft' comes from fgets(3). - lib/gshadow.c: - strlen(string) is calculated a few lines above. - libmisc/console.c: - 'cons' comes from getdef_str, which is a bit cryptic, but seems to generate strings, I guess.1 - libmisc/date_to_str.c: - It receives a string literal. :) - libmisc/utmp.c: - 'tname' comes from ttyname(3), which returns a string. - src/su.c: - 'tmp_name' has been passed to strcmp(3) a few lines above. Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-16 08:43:53 +05:30
}
tm = gmtime(&t);
if (tm == NULL) {
(void) strlcpy(buf, "future", size);
return;
}
(void) strftime(buf, size, "%Y-%m-%d", tm);
buf[size - 1] = '\0';
}