mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 18:22:07 +00:00
rgbasm: Fix TOCTOU and reduce buffering.
This commit is contained in:
4
Makefile
4
Makefile
@@ -22,7 +22,9 @@ rgbasm_obj := \
|
|||||||
src/asm/output.o \
|
src/asm/output.o \
|
||||||
src/asm/rpn.o \
|
src/asm/rpn.o \
|
||||||
src/asm/symbol.o \
|
src/asm/symbol.o \
|
||||||
src/asm/gameboy/locallex.o
|
src/asm/gameboy/locallex.o \
|
||||||
|
src/extern/strlcpy.o \
|
||||||
|
src/extern/strlcat.o
|
||||||
|
|
||||||
rgblib_obj := \
|
rgblib_obj := \
|
||||||
src/lib/library.o \
|
src/lib/library.o \
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
#ifndef ASMOTOR_ASM_FSTACK_H
|
#ifndef ASMOTOR_ASM_FSTACK_H
|
||||||
#define ASMOTOR_ASM_FSTACK_H
|
#define ASMOTOR_ASM_FSTACK_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "asm/asm.h"
|
#include "asm/asm.h"
|
||||||
#include "asm/types.h"
|
#include "asm/types.h"
|
||||||
#include "asm/lexer.h"
|
#include "asm/lexer.h"
|
||||||
@@ -27,14 +29,17 @@ struct sContext {
|
|||||||
ULONG nREPTBlockSize;
|
ULONG nREPTBlockSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern ULONG fstk_RunInclude(char *s);
|
void
|
||||||
|
fstk_RunInclude(char *);
|
||||||
extern void fstk_RunMacroArg(SLONG s);
|
extern void fstk_RunMacroArg(SLONG s);
|
||||||
extern ULONG fstk_Init(char *s);
|
void
|
||||||
|
fstk_Init(char *);
|
||||||
extern void fstk_Dump(void);
|
extern void fstk_Dump(void);
|
||||||
extern void fstk_AddIncludePath(char *s);
|
extern void fstk_AddIncludePath(char *s);
|
||||||
extern ULONG fstk_RunMacro(char *s);
|
extern ULONG fstk_RunMacro(char *s);
|
||||||
extern void fstk_RunRept(ULONG count);
|
extern void fstk_RunRept(ULONG count);
|
||||||
extern void fstk_FindFile(char *s);
|
FILE *
|
||||||
|
fstk_FindFile(char *);
|
||||||
|
|
||||||
extern int yywrap(void);
|
extern int yywrap(void);
|
||||||
|
|
||||||
|
|||||||
111
src/asm/fstack.c
111
src/asm/fstack.c
@@ -5,10 +5,19 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifndef STRL_IN_LIBC
|
||||||
|
#define strlcpy rgbds_strlcpy
|
||||||
|
#define strlcat rgbds_strlcat
|
||||||
|
size_t strlcpy(char *, const char *, size_t);
|
||||||
|
size_t strlcat(char *, const char *, size_t);
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "asm/symbol.h"
|
#include "asm/symbol.h"
|
||||||
#include "asm/fstack.h"
|
#include "asm/fstack.h"
|
||||||
#include "asm/types.h"
|
#include "asm/types.h"
|
||||||
@@ -195,28 +204,33 @@ fstk_AddIncludePath(char *s)
|
|||||||
strcpy(IncludePaths[NextIncPath++], s);
|
strcpy(IncludePaths[NextIncPath++], s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
FILE *
|
||||||
fstk_FindFile(char *s)
|
fstk_FindFile(char *fname)
|
||||||
{
|
{
|
||||||
char t[_MAX_PATH + 1];
|
char path[PATH_MAX];
|
||||||
SLONG i = -1;
|
int i;
|
||||||
|
FILE *f;
|
||||||
|
|
||||||
strcpy(t, s);
|
if ((f = fopen(fname, "rb")) != NULL || errno != ENOENT) {
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
while (i < NextIncPath) {
|
for (i = 0; i < NextIncPath; ++i) {
|
||||||
FILE *f;
|
if (strlcpy(path, IncludePaths[i], sizeof path) >=
|
||||||
|
sizeof path) {
|
||||||
if ((f = fopen(t, "rb")) != NULL) {
|
continue;
|
||||||
fclose(f);
|
|
||||||
strcpy(s, t);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
i += 1;
|
if (strlcat(path, fname, sizeof path) >= sizeof path) {
|
||||||
if (i < NextIncPath) {
|
continue;
|
||||||
strcpy(t, IncludePaths[i]);
|
}
|
||||||
strcat(t, s);
|
|
||||||
|
if ((f = fopen(path, "rb")) != NULL || errno != ENOENT) {
|
||||||
|
return f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
errno = ENOENT;
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* RGBAsm - FSTACK.C (FileStack routines)
|
* RGBAsm - FSTACK.C (FileStack routines)
|
||||||
@@ -225,33 +239,32 @@ fstk_FindFile(char *s)
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ULONG
|
void
|
||||||
fstk_RunInclude(char *tzFileName)
|
fstk_RunInclude(char *tzFileName)
|
||||||
{
|
{
|
||||||
FILE *f;
|
FILE *f;
|
||||||
|
|
||||||
//printf("INCLUDE: %s\n", s);
|
f = fstk_FindFile(tzFileName);
|
||||||
|
|
||||||
fstk_FindFile(tzFileName);
|
if (f == NULL) {
|
||||||
//printf("INCLUDING: %s\n", tzFileName);
|
fprintf(stderr, "Unable to open included file '%s': ",
|
||||||
|
tzFileName);
|
||||||
|
perror(NULL);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
if ((f = fopen(tzFileName, "r")) != NULL) {
|
pushcontext();
|
||||||
pushcontext();
|
nLineNo = 1;
|
||||||
nLineNo = 1;
|
nCurrentStatus = STAT_isInclude;
|
||||||
nCurrentStatus = STAT_isInclude;
|
strcpy(tzCurrentFileName, tzFileName);
|
||||||
strcpy(tzCurrentFileName, tzFileName);
|
pCurrentFile = f;
|
||||||
pCurrentFile = f;
|
CurrentFlexHandle = yy_create_buffer(pCurrentFile);
|
||||||
CurrentFlexHandle = yy_create_buffer(pCurrentFile);
|
yy_switch_to_buffer(CurrentFlexHandle);
|
||||||
yy_switch_to_buffer(CurrentFlexHandle);
|
|
||||||
|
|
||||||
//Dirty hack to give the INCLUDE directive a linefeed
|
//Dirty hack to give the INCLUDE directive a linefeed
|
||||||
|
|
||||||
yyunput('\n');
|
yyunput('\n');
|
||||||
nLineNo -= 1;
|
nLineNo -= 1;
|
||||||
|
|
||||||
return (1);
|
|
||||||
} else
|
|
||||||
return (0);
|
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* RGBAsm - FSTACK.C (FileStack routines)
|
* RGBAsm - FSTACK.C (FileStack routines)
|
||||||
@@ -360,7 +373,7 @@ fstk_RunRept(ULONG count)
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ULONG
|
void
|
||||||
fstk_Init(char *s)
|
fstk_Init(char *s)
|
||||||
{
|
{
|
||||||
char tzFileName[_MAX_PATH + 1];
|
char tzFileName[_MAX_PATH + 1];
|
||||||
@@ -368,17 +381,19 @@ fstk_Init(char *s)
|
|||||||
sym_AddString("__FILE__", s);
|
sym_AddString("__FILE__", s);
|
||||||
|
|
||||||
strcpy(tzFileName, s);
|
strcpy(tzFileName, s);
|
||||||
fstk_FindFile(tzFileName);
|
|
||||||
|
|
||||||
pFileStack = NULL;
|
pFileStack = NULL;
|
||||||
if ((pCurrentFile = fopen(tzFileName, "r")) != NULL) {
|
pCurrentFile = fopen(tzFileName, "rb");
|
||||||
nMacroCount = 0;
|
if (pCurrentFile == NULL) {
|
||||||
nCurrentStatus = STAT_isInclude;
|
fprintf(stderr, "Unable to open file '%s': ",
|
||||||
strcpy(tzCurrentFileName, tzFileName);
|
tzFileName);
|
||||||
CurrentFlexHandle = yy_create_buffer(pCurrentFile);
|
perror(NULL);
|
||||||
yy_switch_to_buffer(CurrentFlexHandle);
|
exit(1);
|
||||||
nLineNo = 1;
|
}
|
||||||
return (1);
|
|
||||||
} else
|
nMacroCount = 0;
|
||||||
return (0);
|
nCurrentStatus = STAT_isInclude;
|
||||||
|
strcpy(tzCurrentFileName, tzFileName);
|
||||||
|
CurrentFlexHandle = yy_create_buffer(pCurrentFile);
|
||||||
|
yy_switch_to_buffer(CurrentFlexHandle);
|
||||||
|
nLineNo = 1;
|
||||||
}
|
}
|
||||||
|
|||||||
111
src/asm/main.c
111
src/asm/main.c
@@ -348,7 +348,6 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
DefaultOptions = CurrentOptions;
|
DefaultOptions = CurrentOptions;
|
||||||
|
|
||||||
/* tzMainfile=argv[argn++]; argc-=1; */
|
|
||||||
tzMainfile = argv[argc - 1];
|
tzMainfile = argv[argc - 1];
|
||||||
|
|
||||||
setuplex();
|
setuplex();
|
||||||
@@ -366,75 +365,71 @@ main(int argc, char *argv[])
|
|||||||
nPass = 1;
|
nPass = 1;
|
||||||
nErrors = 0;
|
nErrors = 0;
|
||||||
sym_PrepPass1();
|
sym_PrepPass1();
|
||||||
if (fstk_Init(tzMainfile)) {
|
fstk_Init(tzMainfile);
|
||||||
if (CurrentOptions.verbose) {
|
if (CurrentOptions.verbose) {
|
||||||
printf("Pass 1...\n");
|
printf("Pass 1...\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
yy_set_state(LEX_STATE_NORMAL);
|
yy_set_state(LEX_STATE_NORMAL);
|
||||||
opt_SetCurrentOptions(&DefaultOptions);
|
opt_SetCurrentOptions(&DefaultOptions);
|
||||||
|
|
||||||
if (yyparse() == 0 && nErrors == 0) {
|
if (yyparse() == 0 && nErrors == 0) {
|
||||||
if (nIFDepth == 0) {
|
if (nIFDepth == 0) {
|
||||||
nTotalLines = 0;
|
nTotalLines = 0;
|
||||||
nLineNo = 1;
|
nLineNo = 1;
|
||||||
nIFDepth = 0;
|
nIFDepth = 0;
|
||||||
nPC = 0;
|
nPC = 0;
|
||||||
nPass = 2;
|
nPass = 2;
|
||||||
nErrors = 0;
|
nErrors = 0;
|
||||||
sym_PrepPass2();
|
sym_PrepPass2();
|
||||||
out_PrepPass2();
|
out_PrepPass2();
|
||||||
fstk_Init(tzMainfile);
|
fstk_Init(tzMainfile);
|
||||||
yy_set_state(LEX_STATE_NORMAL);
|
yy_set_state(LEX_STATE_NORMAL);
|
||||||
opt_SetCurrentOptions(&DefaultOptions);
|
opt_SetCurrentOptions(&DefaultOptions);
|
||||||
|
|
||||||
|
if (CurrentOptions.verbose) {
|
||||||
|
printf("Pass 2...\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (yyparse() == 0 && nErrors == 0) {
|
||||||
|
double timespent;
|
||||||
|
|
||||||
|
nEndClock = clock();
|
||||||
|
timespent =
|
||||||
|
((double) (nEndClock - nStartClock))
|
||||||
|
/ (double) CLOCKS_PER_SEC;
|
||||||
if (CurrentOptions.verbose) {
|
if (CurrentOptions.verbose) {
|
||||||
printf("Pass 2...\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (yyparse() == 0 && nErrors == 0) {
|
|
||||||
double timespent;
|
|
||||||
|
|
||||||
nEndClock = clock();
|
|
||||||
timespent =
|
|
||||||
((double) (nEndClock - nStartClock))
|
|
||||||
/ (double) CLOCKS_PER_SEC;
|
|
||||||
if (CurrentOptions.verbose) {
|
|
||||||
printf
|
|
||||||
("Success! %ld lines in %d.%02d seconds ",
|
|
||||||
nTotalLines, (int) timespent,
|
|
||||||
((int) (timespent * 100.0)) % 100);
|
|
||||||
if (timespent == 0)
|
|
||||||
printf
|
|
||||||
("(INFINITY lines/minute)\n");
|
|
||||||
else
|
|
||||||
printf("(%d lines/minute)\n",
|
|
||||||
(int) (60 / timespent *
|
|
||||||
nTotalLines));
|
|
||||||
}
|
|
||||||
out_WriteObject();
|
|
||||||
} else {
|
|
||||||
printf
|
printf
|
||||||
("Assembly aborted in pass 2 (%ld errors)!\n",
|
("Success! %ld lines in %d.%02d seconds ",
|
||||||
nErrors);
|
nTotalLines, (int) timespent,
|
||||||
//sym_PrintSymbolTable();
|
((int) (timespent * 100.0)) % 100);
|
||||||
exit(5);
|
if (timespent == 0)
|
||||||
|
printf
|
||||||
|
("(INFINITY lines/minute)\n");
|
||||||
|
else
|
||||||
|
printf("(%d lines/minute)\n",
|
||||||
|
(int) (60 / timespent *
|
||||||
|
nTotalLines));
|
||||||
}
|
}
|
||||||
|
out_WriteObject();
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr,
|
printf
|
||||||
"Unterminated IF construct (%ld levels)!\n",
|
("Assembly aborted in pass 2 (%ld errors)!\n",
|
||||||
nIFDepth);
|
nErrors);
|
||||||
exit(1);
|
//sym_PrintSymbolTable();
|
||||||
|
exit(5);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Assembly aborted in pass 1 (%ld errors)!\n",
|
"Unterminated IF construct (%ld levels)!\n",
|
||||||
nErrors);
|
nIFDepth);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
printf("File '%s' not found\n", tzMainfile);
|
fprintf(stderr,
|
||||||
exit(5);
|
"Assembly aborted in pass 1 (%ld errors)!\n",
|
||||||
|
nErrors);
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
return (0);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -907,30 +907,33 @@ out_BinaryFile(char *s)
|
|||||||
{
|
{
|
||||||
FILE *f;
|
FILE *f;
|
||||||
|
|
||||||
fstk_FindFile(s);
|
f = fstk_FindFile(s);
|
||||||
|
if (f == NULL) {
|
||||||
|
fprintf(stderr, "Unable to open incbin file '%s': ",
|
||||||
|
s);
|
||||||
|
perror(NULL);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
if ((f = fopen(s, "rb")) != NULL) {
|
SLONG fsize;
|
||||||
SLONG fsize;
|
|
||||||
|
|
||||||
fseek(f, 0, SEEK_END);
|
fseek(f, 0, SEEK_END);
|
||||||
fsize = ftell(f);
|
fsize = ftell(f);
|
||||||
fseek(f, 0, SEEK_SET);
|
fseek(f, 0, SEEK_SET);
|
||||||
|
|
||||||
checkcodesection(fsize);
|
checkcodesection(fsize);
|
||||||
|
|
||||||
if (nPass == 2) {
|
if (nPass == 2) {
|
||||||
SLONG dest = nPC;
|
SLONG dest = nPC;
|
||||||
SLONG todo = fsize;
|
SLONG todo = fsize;
|
||||||
|
|
||||||
while (todo--)
|
while (todo--)
|
||||||
pCurrentSection->tData[dest++] = fgetc(f);
|
pCurrentSection->tData[dest++] = fgetc(f);
|
||||||
}
|
}
|
||||||
pCurrentSection->nPC += fsize;
|
pCurrentSection->nPC += fsize;
|
||||||
nPC += fsize;
|
nPC += fsize;
|
||||||
pPCSymbol->nValue += fsize;
|
pPCSymbol->nValue += fsize;
|
||||||
fclose(f);
|
fclose(f);
|
||||||
} else
|
|
||||||
fatalerror("Could not open file '%s': %s", s, strerror(errno));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -944,36 +947,39 @@ out_BinaryFileSlice(char *s, SLONG start_pos, SLONG length)
|
|||||||
if (length < 0)
|
if (length < 0)
|
||||||
fatalerror("Number of bytes to read must be greater than zero");
|
fatalerror("Number of bytes to read must be greater than zero");
|
||||||
|
|
||||||
fstk_FindFile(s);
|
f = fstk_FindFile(s);
|
||||||
|
if (f == NULL) {
|
||||||
|
fprintf(stderr, "Unable to open included file '%s': ",
|
||||||
|
s);
|
||||||
|
perror(NULL);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
if ((f = fopen(s, "rb")) != NULL) {
|
SLONG fsize;
|
||||||
SLONG fsize;
|
|
||||||
|
|
||||||
fseek(f, 0, SEEK_END);
|
fseek(f, 0, SEEK_END);
|
||||||
fsize = ftell(f);
|
fsize = ftell(f);
|
||||||
|
|
||||||
if (start_pos >= fsize)
|
if (start_pos >= fsize)
|
||||||
fatalerror("Specified start position is greater than length of file");
|
fatalerror("Specified start position is greater than length of file");
|
||||||
|
|
||||||
if ((start_pos + length) > fsize)
|
if ((start_pos + length) > fsize)
|
||||||
fatalerror("Specified range in INCBIN is out of bounds");
|
fatalerror("Specified range in INCBIN is out of bounds");
|
||||||
|
|
||||||
fseek(f, start_pos, SEEK_SET);
|
fseek(f, start_pos, SEEK_SET);
|
||||||
|
|
||||||
checkcodesection(length);
|
checkcodesection(length);
|
||||||
|
|
||||||
if (nPass == 2) {
|
if (nPass == 2) {
|
||||||
SLONG dest = nPC;
|
SLONG dest = nPC;
|
||||||
SLONG todo = length;
|
SLONG todo = length;
|
||||||
|
|
||||||
while (todo--)
|
while (todo--)
|
||||||
pCurrentSection->tData[dest++] = fgetc(f);
|
pCurrentSection->tData[dest++] = fgetc(f);
|
||||||
}
|
}
|
||||||
pCurrentSection->nPC += length;
|
pCurrentSection->nPC += length;
|
||||||
nPC += length;
|
nPC += length;
|
||||||
pPCSymbol->nValue += length;
|
pPCSymbol->nValue += length;
|
||||||
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
} else
|
|
||||||
fatalerror("Could not open file '%s': %s", s, strerror(errno));
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -265,10 +265,7 @@ set : T_LABEL T_POP_SET const
|
|||||||
|
|
||||||
include : T_POP_INCLUDE string
|
include : T_POP_INCLUDE string
|
||||||
{
|
{
|
||||||
if( !fstk_RunInclude($2) )
|
fstk_RunInclude($2);
|
||||||
{
|
|
||||||
yyerror("Could not open file '%s' : %s\n", $2, strerror(errno));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|||||||
55
src/extern/strlcat.c
vendored
Normal file
55
src/extern/strlcat.c
vendored
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
/* $OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1998 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 siz (unlike strncat, siz is the
|
||||||
|
* full size of dst, not space left). At most siz-1 characters
|
||||||
|
* will be copied. Always NUL terminates (unless siz <= strlen(dst)).
|
||||||
|
* Returns strlen(src) + MIN(siz, strlen(initial dst)).
|
||||||
|
* If retval >= siz, truncation occurred.
|
||||||
|
*/
|
||||||
|
size_t
|
||||||
|
rgbds_strlcat(char *dst, const char *src, size_t siz)
|
||||||
|
{
|
||||||
|
char *d = dst;
|
||||||
|
const char *s = src;
|
||||||
|
size_t n = siz;
|
||||||
|
size_t dlen;
|
||||||
|
|
||||||
|
/* Find the end of dst and adjust bytes left but don't go past end */
|
||||||
|
while (n-- != 0 && *d != '\0')
|
||||||
|
d++;
|
||||||
|
dlen = d - dst;
|
||||||
|
n = siz - dlen;
|
||||||
|
|
||||||
|
if (n == 0)
|
||||||
|
return(dlen + strlen(s));
|
||||||
|
while (*s != '\0') {
|
||||||
|
if (n != 1) {
|
||||||
|
*d++ = *s;
|
||||||
|
n--;
|
||||||
|
}
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
*d = '\0';
|
||||||
|
|
||||||
|
return(dlen + (s - src)); /* count does not include NUL */
|
||||||
|
}
|
||||||
51
src/extern/strlcpy.c
vendored
Normal file
51
src/extern/strlcpy.c
vendored
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
/* $OpenBSD: strlcpy.c,v 1.11 2006/05/05 15:27:38 millert Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1998 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 src to string dst of size siz. At most siz-1 characters
|
||||||
|
* will be copied. Always NUL terminates (unless siz == 0).
|
||||||
|
* Returns strlen(src); if retval >= siz, truncation occurred.
|
||||||
|
*/
|
||||||
|
size_t
|
||||||
|
rgbds_strlcpy(char *dst, const char *src, size_t siz)
|
||||||
|
{
|
||||||
|
char *d = dst;
|
||||||
|
const char *s = src;
|
||||||
|
size_t n = siz;
|
||||||
|
|
||||||
|
/* Copy as many bytes as will fit */
|
||||||
|
if (n != 0) {
|
||||||
|
while (--n != 0) {
|
||||||
|
if ((*d++ = *s++) == '\0')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Not enough room in dst, add NUL and traverse rest of src */
|
||||||
|
if (n == 0) {
|
||||||
|
if (siz != 0)
|
||||||
|
*d = '\0'; /* NUL-terminate dst */
|
||||||
|
while (*s++)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
return(s - src - 1); /* count does not include NUL */
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user