Import strlcpy/strlcat from OpenBSD, start using them.

strcpy()/strcat() are inherently dangerous, even when
used with great care.  strlcpy() and strlcat() are
much safer replacements, and are available from OpenBSD
under a very liberal license.  Import them and start
using them.

Between pointer vectors, malloz, stralloc and now
strlcpy/strlcat, Magicka has much safer, simpler and
more performant infrastructure for dealing with
strings and dynamic collections of various kinds.

Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
This commit is contained in:
Dan Cross 2018-10-11 02:49:23 +00:00 committed by Andrew Pamment
parent 77bf763939
commit 6d30116ed9
11 changed files with 149 additions and 33 deletions

View File

@ -50,7 +50,8 @@ HDRS:= bbs.h
OBJS:= inih/ini.o bbs.o main.o users.o main_menu.o mail_menu.o \ OBJS:= inih/ini.o bbs.o main.o users.o main_menu.o mail_menu.o \
doors.o bbs_list.o chat_system.o email.o files.o settings.o \ doors.o bbs_list.o chat_system.o email.o files.o settings.o \
lua_glue.o strings.o bluewave.o hashmap/hashmap.o menus.o \ lua_glue.o strings.o bluewave.o hashmap/hashmap.o menus.o \
nodelist.o blog.o util.o stralloc/stralloc.o nodelist.o blog.o util.o stralloc/stralloc.o strlcpy/strlcpy.o \
strlcpy/strlcat.o
WWWOBJS:= ../deps/aha/aha.o ../deps/hashids/hashids.o www.o www_email.o \ WWWOBJS:= ../deps/aha/aha.o ../deps/hashids/hashids.o www.o www_email.o \
www_msgs.o www_last10.o www_blog.o www_files.o ${OBJS} www_msgs.o www_last10.o www_blog.o www_files.o ${OBJS}

View File

@ -536,7 +536,7 @@ void s_readstring_inject(char *buffer, int max, char *inject) {
return; return;
} }
strcpy(buffer, inject); strlcpy(buffer, inject, max);
s_printf("%s", inject); s_printf("%s", inject);
@ -686,8 +686,8 @@ void record_last10_callers(struct user_record *user) {
if (strcasecmp(conf.sysop_name, user->loginname) != 0) { if (strcasecmp(conf.sysop_name, user->loginname) != 0) {
memset(&new_entry, 0, sizeof(struct last10_callers)); memset(&new_entry, 0, sizeof(struct last10_callers));
strcpy(new_entry.name, user->loginname); strlcpy(new_entry.name, user->loginname, sizeof(new_entry.name));
strcpy(new_entry.location, user->location); strlcpy(new_entry.location, user->location, sizeof(new_entry.location));
new_entry.time = time(NULL); new_entry.time = time(NULL);
new_entry.calls = user->timeson; new_entry.calls = user->timeson;
if (i == 10) { if (i == 10) {
@ -777,7 +777,7 @@ void automessage_write() {
timen = time(NULL); timen = time(NULL);
localtime_r(&timen, &timenow); localtime_r(&timen, &timenow);
sprintf(automsg, get_string(15), gUser->loginname, asctime(&timenow)); snprintf(automsg, sizeof automsg, get_string(15), gUser->loginname, asctime(&timenow));
automsg[strlen(automsg) - 1] = '\r'; automsg[strlen(automsg) - 1] = '\r';
automsg[strlen(automsg)] = '\n'; automsg[strlen(automsg)] = '\n';
@ -785,8 +785,8 @@ void automessage_write() {
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
s_printf("\r\n%d: ", i); s_printf("\r\n%d: ", i);
s_readstring(buffer, 75); s_readstring(buffer, 75);
strcat(automsg, buffer); strlcat(automsg, buffer, sizeof automsg);
strcat(automsg, "\r\n"); strlcat(automsg, "\r\n", sizeof automsg);
} }
fptr = fopen("automessage.txt", "w"); fptr = fopen("automessage.txt", "w");
@ -1346,7 +1346,7 @@ char *str_replace(const char *str, const char *from, const char *to) {
if (count == 0) { if (count == 0) {
/* If no matches, then just duplicate the string. */ /* If no matches, then just duplicate the string. */
strcpy(ret, str); strlcpy(ret, str, retlen + 1);
} else { } else {
/* Otherwise, duplicate the string whilst performing /* Otherwise, duplicate the string whilst performing
* the replacements using the position cache. */ * the replacements using the position cache. */

View File

@ -3,6 +3,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <stddef.h>
#include <time.h> #include <time.h>
#include <termios.h> #include <termios.h>
#ifdef __APPLE__ #ifdef __APPLE__
@ -11,12 +12,17 @@
#if defined(ENABLE_WWW) #if defined(ENABLE_WWW)
#include <microhttpd.h> #include <microhttpd.h>
#endif #endif
#include <string.h>
#include "lua/lua.h" #include "lua/lua.h"
#include "lua/lauxlib.h" #include "lua/lauxlib.h"
#include "jamlib/jam.h" #include "jamlib/jam.h"
#include "stralloc/stralloc.h" #include "stralloc/stralloc.h"
#ifndef __linux__
#define HAVE_STRLCPY
#endif
#define VERSION_MAJOR 0 #define VERSION_MAJOR 0
#define VERSION_MINOR 12 #define VERSION_MINOR 12
#define VERSION_STR "alpha" #define VERSION_STR "alpha"
@ -405,6 +411,11 @@ extern char *str4dup(const char *a, const char *b, const char *c, const char *d)
extern char *str3dup(const char *a, const char *b, const char *c); extern char *str3dup(const char *a, const char *b, const char *c);
extern char *str2dup(const char *a, const char *b); extern char *str2dup(const char *a, const char *b);
#if !defined(HAVE_STRLCPY)
extern size_t strlcat(char *dst, const char *src, size_t dsize);
extern size_t strlcpy(char *dst, const char *src, size_t dsize);
#endif
#if defined(ENABLE_WWW) #if defined(ENABLE_WWW)
extern void www_init(); extern void www_init();
extern void *www_logger(void *cls, const char *uri, struct MHD_Connection *con); extern void *www_logger(void *cls, const char *uri, struct MHD_Connection *con);

View File

@ -591,9 +591,9 @@ int bwave_add_message(int confr, int area, unsigned int dwritten, char *to, char
jmh.DateWritten = dwritten; jmh.DateWritten = dwritten;
jmh.Attribute |= JAM_MSG_LOCAL; jmh.Attribute |= JAM_MSG_LOCAL;
if (conf.mail_conferences[confr]->realnames == 0) { if (conf.mail_conferences[confr]->realnames == 0) {
strcpy(buffer, gUser->loginname); strlcpy(buffer, gUser->loginname, sizeof buffer);
} else { } else {
sprintf(buffer, "%s %s", gUser->firstname, gUser->lastname); snprintf(buffer, sizeof buffer, "%s %s", gUser->firstname, gUser->lastname);
} }
jsp = JAM_NewSubPacket(); jsp = JAM_NewSubPacket();

View File

@ -432,8 +432,8 @@ void chat_system(struct user_record *user) {
return; return;
} }
strncat(partmessage, readbuffer, len); strlcat(partmessage, readbuffer, sizeof(partmessage));
strcpy(readbuffer, partmessage); strlcpy(readbuffer, partmessage, sizeof(readbuffer));
y = 0; y = 0;
for (z = 0; z < strlen(readbuffer); z++) { for (z = 0; z < strlen(readbuffer); z++) {

View File

@ -91,7 +91,7 @@ int write_door32sys(struct user_record *user) {
return 1; return 1;
} }
strcpy(buffer, conf.sysop_name); strlcpy(buffer, conf.sysop_name, sizeof(buffer));
ptr = NULL; ptr = NULL;

View File

@ -170,7 +170,7 @@ void show_email(struct user_record *user, int msgno, int email_count, struct ema
if (z == start_line) { if (z == start_line) {
line[0] = '\0'; line[0] = '\0';
} else { } else {
strncpy(line, &emails[msgno]->body[start_line], z - start_line); strlcpy(line, &emails[msgno]->body[start_line], z - start_line + 1);
line[z - start_line] = '\0'; line[z - start_line] = '\0';
} }
if (emails[msgno]->body[z] == '\r') { if (emails[msgno]->body[z] == '\r') {

View File

@ -531,10 +531,10 @@ char *external_editor(struct user_record *user, char *to, char *from, char *quot
if (!sig) { if (!sig) {
if (user->autosig) { if (user->autosig) {
strcat(body2, "\r"); strlcat(body2, "\r", totlen + 1);
strcat(body2, user->signature); strlcat(body2, user->signature, totlen + 1);
} }
strcat(body2, buffer); strlcat(body2, buffer, totlen + 1);
} }
free(body); free(body);
@ -594,7 +594,7 @@ char *editor(struct user_record *user, char *quote, int quotelen, char *from, in
while (!doquit) { while (!doquit) {
s_printf(get_string(88), lines, ""); s_printf(get_string(88), lines, "");
strcpy(linebuffer, next_line_buffer); strlcpy(linebuffer, next_line_buffer, sizeof(linebuffer));
s_readstring_inject(linebuffer, 70, next_line_buffer); s_readstring_inject(linebuffer, 70, next_line_buffer);
memset(next_line_buffer, 0, 70); memset(next_line_buffer, 0, 70);
@ -602,7 +602,7 @@ char *editor(struct user_record *user, char *quote, int quotelen, char *from, in
for (i = strlen(linebuffer) - 1; i > 15; i--) { for (i = strlen(linebuffer) - 1; i > 15; i--) {
if (linebuffer[i] == ' ') { if (linebuffer[i] == ' ') {
linebuffer[i] = '\0'; linebuffer[i] = '\0';
strcpy(next_line_buffer, &linebuffer[i + 1]); strlcpy(next_line_buffer, &linebuffer[i + 1], sizeof next_line_buffer);
s_printf("\e[%dD\e[0K", 70 - i); s_printf("\e[%dD\e[0K", 70 - i);
break; break;
} }
@ -654,18 +654,18 @@ char *editor(struct user_record *user, char *quote, int quotelen, char *from, in
msg = (char *)malloz(size); msg = (char *)malloz(size);
for (i = 0; i < ptr_vector_len(&content); i++) { for (i = 0; i < ptr_vector_len(&content); i++) {
strcat(msg, ptr_vector_get(&content, i)); strlcat(msg, ptr_vector_get(&content, i), size);
strcat(msg, "\r"); strlcat(msg, "\r", size);
} }
ptr_vector_apply(&content, free); ptr_vector_apply(&content, free);
destroy_ptr_vector(&content); destroy_ptr_vector(&content);
if (!sig) { if (!sig) {
if (user->autosig) { if (user->autosig) {
strcat(msg, "\r"); strlcat(msg, "\r", size);
strcat(msg, user->signature); strlcat(msg, user->signature, size);
} }
strcat(msg, buffer); strlcat(msg, buffer, size);
} }
if (quote != NULL) { if (quote != NULL) {
@ -1520,7 +1520,7 @@ int read_message(struct user_record *user, struct msg_headers *msghs, int mailno
if (z == start_line) { if (z == start_line) {
msg_line[0] = '\0'; msg_line[0] = '\0';
} else { } else {
strncpy(msg_line, &body[start_line], z - start_line); strlcpy(msg_line, &body[start_line], z - start_line + 1);
msg_line[z - start_line] = '\0'; msg_line[z - start_line] = '\0';
} }
if (body[z] == '\r') { if (body[z] == '\r') {
@ -1634,7 +1634,7 @@ int read_message(struct user_record *user, struct msg_headers *msghs, int mailno
s_printf("\r\n"); s_printf("\r\n");
if (msghs->msgs[mailno]->from != NULL) { if (msghs->msgs[mailno]->from != NULL) {
strcpy(buffer, msghs->msgs[mailno]->from); strlcpy(buffer, msghs->msgs[mailno]->from, sizeof buffer);
} }
if (conf.mail_conferences[user->cur_mail_conf]->realnames == 0) { if (conf.mail_conferences[user->cur_mail_conf]->realnames == 0) {
from = strdup(user->loginname); from = strdup(user->loginname);
@ -1643,8 +1643,7 @@ int read_message(struct user_record *user, struct msg_headers *msghs, int mailno
} }
if (conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->type == TYPE_NEWSGROUP_AREA) { if (conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->type == TYPE_NEWSGROUP_AREA) {
free(to); free(to);
to = (char *)malloz(4); to = strdup("ALL");
strcpy(to, "ALL");
} }
replybody = external_editor(user, to, from, body, z2, msghs->msgs[mailno]->from, subject, 0, 0); replybody = external_editor(user, to, from, body, z2, msghs->msgs[mailno]->from, subject, 0, 0);
if (replybody != NULL) { if (replybody != NULL) {
@ -2064,7 +2063,7 @@ void post_message(struct user_record *user) {
s_readstring(buffer, 32); s_readstring(buffer, 32);
} }
if (strlen(buffer) == 0) { if (strlen(buffer) == 0) {
strcpy(buffer, "ALL"); strlcpy(buffer, "ALL", sizeof(buffer));
} }
if (conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->type == TYPE_NETMAIL_AREA) { if (conf.mail_conferences[user->cur_mail_conf]->mail_areas[user->cur_mail_area]->type == TYPE_NETMAIL_AREA) {
@ -2129,9 +2128,9 @@ void post_message(struct user_record *user) {
jmh.DateWritten = (uint32_t)utc_to_local(time(NULL)); jmh.DateWritten = (uint32_t)utc_to_local(time(NULL));
jmh.Attribute |= JAM_MSG_LOCAL; jmh.Attribute |= JAM_MSG_LOCAL;
if (conf.mail_conferences[user->cur_mail_conf]->realnames == 0) { if (conf.mail_conferences[user->cur_mail_conf]->realnames == 0) {
strcpy(buffer, user->loginname); strlcpy(buffer, user->loginname, sizeof(buffer));
} else { } else {
sprintf(buffer, "%s %s", user->firstname, user->lastname); snprintf(buffer, sizeof buffer, "%s %s", user->firstname, user->lastname);
} }
jsp = JAM_NewSubPacket(); jsp = JAM_NewSubPacket();

55
src/strlcpy/strlcat.c Normal file
View File

@ -0,0 +1,55 @@
/* $OpenBSD: strlcat.c,v 1.18 2016/10/16 17:37:39 dtucker Exp $ */
/*
* Copyright (c) 1998, 2015 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <string.h>
/*
* Appends src to string dst of size dsize (unlike strncat, dsize is the
* full size of dst, not space left). At most dsize-1 characters
* will be copied. Always NUL terminates (unless dsize <= strlen(dst)).
* Returns strlen(src) + MIN(dsize, strlen(initial dst)).
* If retval >= dsize, truncation occurred.
*/
size_t
strlcat(char *dst, const char *src, size_t dsize)
{
const char *odst = dst;
const char *osrc = src;
size_t n = dsize;
size_t dlen;
/* Find the end of dst and adjust bytes left but don't go past end. */
while (n-- != 0 && *dst != '\0')
dst++;
dlen = dst - odst;
n = dsize - dlen;
if (n-- == 0)
return(dlen + strlen(src));
while (*src != '\0') {
if (n != 0) {
*dst++ = *src;
n--;
}
src++;
}
*dst = '\0';
return(dlen + (src - osrc)); /* count does not include NUL */
}

50
src/strlcpy/strlcpy.c Normal file
View File

@ -0,0 +1,50 @@
/* $OpenBSD: strlcpy.c,v 1.15 2016/10/16 17:37:39 dtucker Exp $ */
/*
* Copyright (c) 1998, 2015 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <string.h>
/*
* Copy string src to buffer dst of size dsize. At most dsize-1
* chars will be copied. Always NUL terminates (unless dsize == 0).
* Returns strlen(src); if retval >= dsize, truncation occurred.
*/
size_t
strlcpy(char *dst, const char *src, size_t dsize)
{
const char *osrc = src;
size_t nleft = dsize;
/* Copy as many bytes as will fit. */
if (nleft != 0) {
while (--nleft != 0) {
if ((*dst++ = *src++) == '\0')
break;
}
}
/* Not enough room in dst, add NUL and traverse rest of src. */
if (nleft == 0) {
if (dsize != 0)
*dst = '\0'; /* NUL-terminate dst */
while (*src++)
;
}
return(src - osrc - 1); /* count does not include NUL */
}

View File

@ -870,9 +870,9 @@ int www_send_msg(struct user_record *user, char *to, char *subj, int conference,
jmh.Attribute |= JAM_MSG_LOCAL; jmh.Attribute |= JAM_MSG_LOCAL;
if (conf.mail_conferences[conference]->realnames == 0) { if (conf.mail_conferences[conference]->realnames == 0) {
strcpy(buffer, user->loginname); strlcpy(buffer, user->loginname, sizeof buffer);
} else { } else {
sprintf(buffer, "%s %s", user->firstname, user->lastname); snprintf(buffer, sizeof buffer, "%s %s", user->firstname, user->lastname);
} }
jsp = JAM_NewSubPacket(); jsp = JAM_NewSubPacket();