Remove arbitrary limit on config file line lengths.

Stop using the namebuff buffer to read config file
lines. This reduced in size in
014e909f78 and caused
regressions. We now resize the buffer as needed,
so there is no practical limit.

Use the same code to remove the same limit when reading
/etc/ethers and /etc/resolv.conf. Also when copying output
from the lease-change script into the log.

Thanks to Kevin Darbyshire-Bryant for finding the regresssion.
This commit is contained in:
Simon Kelley committed 2026-05-16 21:37:11 +01:00
1 parent 14094e88be
commit 228d7ff964
7 files changed
+109 -59

No files matched your search

+7 -6
View File
@@ -1407,9 +1407,10 @@ static int eatspace(FILE *f)
}
}
static int gettok(FILE *f, char *token)
static int gettok(FILE *f, char *token, size_t buffsz)
{
int c, count = 0;
int c;
unsigned int count = 0;
while (1)
{
@@ -1422,7 +1423,7 @@ static int gettok(FILE *f, char *token)
return eatspace(f);
}
if (count < (MAXDNAMESTR - 1))
if (count < (buffsz - 1))
{
token[count++] = c;
token[count] = 0;
@@ -1447,7 +1448,7 @@ int read_hostsfile(char *filename, unsigned int index, int cache_size, struct cr
lineno += eatspace(f);
while ((atnl = gettok(f, token)) != -1)
while ((atnl = gettok(f, token, MAXDNAMESTR)) != -1)
{
if (inet_pton(AF_INET, token, &addr) > 0)
{
@@ -1465,7 +1466,7 @@ int read_hostsfile(char *filename, unsigned int index, int cache_size, struct cr
{
my_syslog(LOG_ERR, _("bad address at %s line %d"), filename, lineno);
while (atnl == 0)
atnl = gettok(f, token);
atnl = gettok(f, token, MAXDNAMESTR);
lineno += atnl;
continue;
}
@@ -1483,7 +1484,7 @@ int read_hostsfile(char *filename, unsigned int index, int cache_size, struct cr
int fqdn, nomem;
char *canon;
if ((atnl = gettok(f, token)) == -1)
if ((atnl = gettok(f, token, MAXDNAMESTR)) == -1)
break;
fqdn = !!strchr(token, '.');
+8 -7
View File
@@ -925,7 +925,8 @@ void dhcp_read_ethers(void)
{
FILE *f = fopen(ETHERSFILE, "r");
unsigned int flags;
char *buff = daemon->namebuff;
size_t linesz = 0;
char *line = NULL;
char *ip, *cp;
struct in_addr addr;
unsigned char hwaddr[ETHER_ADDR_LEN];
@@ -958,22 +959,22 @@ void dhcp_read_ethers(void)
up = &config->next;
}
while (fgets(buff, MAXDNAMESTR, f))
while (get_line_alloc(f, &line, &linesz))
{
char *host = NULL;
lineno++;
while (strlen(buff) > 0 && isspace((unsigned char)buff[strlen(buff)-1]))
buff[strlen(buff)-1] = 0;
while (strlen(line) > 0 && isspace((unsigned char)line[strlen(line)-1]))
line[strlen(line)-1] = 0;
if ((*buff == '#') || (*buff == '+') || (*buff == 0))
if ((*line == '#') || (*line == '+') || (*line == 0))
continue;
for (ip = buff; *ip && !isspace((unsigned char)*ip); ip++);
for (ip = line; *ip && !isspace((unsigned char)*ip); ip++);
for(; *ip && isspace((unsigned char)*ip); ip++)
*ip = 0;
if (!*ip || parse_hex(buff, hwaddr, ETHER_ADDR_LEN, NULL, NULL) != ETHER_ADDR_LEN)
if (!*ip || parse_hex(line, hwaddr, ETHER_ADDR_LEN, NULL, NULL) != ETHER_ADDR_LEN)
{
my_syslog(MS_DHCP | LOG_ERR, _("bad line at %s line %d"), ETHERSFILE, lineno);
continue;
+1
View File
@@ -1516,6 +1516,7 @@ void *whine_malloc_real(const char *func, unsigned int line, size_t size);
void *whine_realloc_real(const char *wrapper, const char *func, unsigned int line, void *ptr, size_t size);
int expand_buf_real(const char *func, unsigned int line, struct iovec *iov, size_t size);
int expand_workspace_real(const char *func, unsigned int line, unsigned char ***wkspc, int *szp, int new);
int get_line_alloc(FILE *f, char **buffp, size_t *sizep);
int sa_len(union mysockaddr *addr);
int sockaddr_isequal(const union mysockaddr *s1, const union mysockaddr *s2);
int sockaddr_isnull(const union mysockaddr *s);
+6 -12
View File
@@ -533,18 +533,12 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
close(pipeout[0]);
else
{
while (fgets(daemon->packet, daemon->packet_buff_sz, fp))
{
/* do not include new lines, log will append them */
size_t len = strlen(daemon->packet);
if (len > 0)
{
--len;
if (daemon->packet[len] == '\n')
daemon->packet[len] = 0;
}
send_event(event_fd, EVENT_SCRIPT_LOG, 0, daemon->packet);
}
char *line = NULL;
size_t linesz = 0;
while (get_line_alloc(fp, &line, &linesz))
send_event(event_fd, EVENT_SCRIPT_LOG, 0, line);
fclose(fp);
}
}
+5 -5
View File
@@ -1699,19 +1699,19 @@ void check_servers(int no_loop_check)
int reload_servers(char *fname)
{
FILE *f;
char *line;
char *line = NULL;
size_t linesz = 0;
int gotone = 0;
/* buff happens to be MAXDNAMESTR long... */
if (!(f = fopen(fname, "r")))
{
my_syslog(LOG_ERR, _("failed to read %s: %s"), fname, strerror(errno));
return 0;
}
mark_servers(SERV_FROM_RESOLV);
while ((line = fgets(daemon->namebuff, MAXDNAMESTR, f)))
while (get_line_alloc(f, &line, &linesz))
{
union mysockaddr addr, source_addr;
char *token = strtok(line, " \t\n\r");
+32 -29
View File
@@ -5471,9 +5471,20 @@ err:
static void read_file(char *file, FILE *f, int hard_opt, int from_script)
{
volatile int lineno = 0;
char *buff = daemon->namebuff;
char *buff;
size_t buffsz;
/* Memory allocation failure longjmps here if mem_recover == 1 */
if (hard_opt != 0)
{
setjmp(mem_jmp);
mem_recover = 1;
}
while (fgets(buff, MAXDNAMESTR, f))
buff = NULL;
buffsz = 0;
while (get_line_alloc(f, &buff, &buffsz))
{
int white, i;
volatile int option;
@@ -5481,15 +5492,7 @@ static void read_file(char *file, FILE *f, int hard_opt, int from_script)
size_t len;
option = (hard_opt == LOPT_REV_SERV) ? 0 : hard_opt;
/* Memory allocation failure longjmps here if mem_recover == 1 */
if (option != 0 || hard_opt == LOPT_REV_SERV)
{
if (setjmp(mem_jmp))
continue;
mem_recover = 1;
}
arg = NULL;
lineno++;
errmess = NULL;
@@ -5949,16 +5952,15 @@ void reread_dhcp(void)
void read_opts(int argc, char **argv, char *compile_opts)
{
size_t argbuf_size = 300;
char *argbuf = opt_malloc(argbuf_size);
char *buff = opt_malloc(MAXDNAMESTR+1);
char *argbuf = safe_malloc(argbuf_size);
int option, testmode = 0;
char *arg, *conffile = NULL;
opterr = 0;
daemon = opt_malloc(sizeof(struct daemon));
memset(daemon, 0, sizeof(struct daemon));
daemon->namebuff = buff;
daemon->namebuff = safe_malloc(MAXDNAMESTR+1);
daemon->workspacename = safe_malloc(MAXDNAMESTR+1);
daemon->addrbuff = safe_malloc(ADDRSTRLEN);
@@ -6197,9 +6199,9 @@ void read_opts(int argc, char **argv, char *compile_opts)
/* create default, if not specified */
if (daemon->authserver && !daemon->hostmaster)
{
strcpy(buff, "hostmaster.");
strcat(buff, daemon->authserver);
daemon->hostmaster = opt_string_alloc(buff);
strcpy(daemon->namebuff, "hostmaster.");
strncat(daemon->namebuff, daemon->authserver, MAXDNAMESTR - strlen(daemon->namebuff));
daemon->hostmaster = opt_string_alloc(daemon->namebuff);
}
if (!daemon->dhcp_pxe_vendors)
@@ -6214,11 +6216,11 @@ void read_opts(int argc, char **argv, char *compile_opts)
{
struct mx_srv_record *mx;
if (gethostname(buff, MAXDNAMESTR) == -1)
if (gethostname(daemon->namebuff, MAXDNAMESTR) == -1)
die(_("cannot get host-name: %s"), NULL, EC_MISC);
for (mx = daemon->mxnames; mx; mx = mx->next)
if (!mx->issrv && hostname_isequal(mx->name, buff))
if (!mx->issrv && hostname_isequal(mx->name, daemon->namebuff))
break;
if ((daemon->mxtarget || option_bool(OPT_LOCALMX)) && !mx)
@@ -6227,12 +6229,12 @@ void read_opts(int argc, char **argv, char *compile_opts)
mx->next = daemon->mxnames;
mx->issrv = 0;
mx->target = NULL;
mx->name = opt_string_alloc(buff);
mx->name = opt_string_alloc(daemon->namebuff);
daemon->mxnames = mx;
}
if (!daemon->mxtarget)
daemon->mxtarget = opt_string_alloc(buff);
daemon->mxtarget = opt_string_alloc(daemon->namebuff);
for (mx = daemon->mxnames; mx; mx = mx->next)
if (!mx->issrv && !mx->target)
@@ -6247,7 +6249,8 @@ void read_opts(int argc, char **argv, char *compile_opts)
if (option_bool(OPT_RESOLV_DOMAIN))
{
char *line;
char *line = NULL;
size_t linesz = 0;
FILE *f;
if (option_bool(OPT_NO_RESOLV) ||
@@ -6258,7 +6261,7 @@ void read_opts(int argc, char **argv, char *compile_opts)
if (!(f = fopen((daemon->resolv_files)->name, "r")))
die(_("failed to read %s: %s"), (daemon->resolv_files)->name, EC_FILE);
while ((line = fgets(buff, MAXDNAMESTR, f)))
while (get_line_alloc(f, &line, &linesz))
{
char *token = strtok(line, " \t\n\r");
@@ -6278,7 +6281,7 @@ void read_opts(int argc, char **argv, char *compile_opts)
if (daemon->domain_suffix)
{
/* add domain for any srv record without one. */
/* add domain for any srv record without one. */
struct mx_srv_record *srv;
for (srv = daemon->mxnames; srv; srv = srv->next)
@@ -6288,11 +6291,11 @@ void read_opts(int argc, char **argv, char *compile_opts)
{
if (strlen(srv->name) + 1 + strlen(daemon->domain_suffix) > MAXDNAMESTR)
die(_("srv-host name %s too long after domain appended"), srv->name, EC_MISC);
strcpy(buff, srv->name);
strcat(buff, ".");
strcat(buff, daemon->domain_suffix);
strcpy(daemon->namebuff, srv->name);
strcat(daemon->namebuff, ".");
strcat(daemon->namebuff, daemon->domain_suffix);
free(srv->name);
if (!(srv->name = canonicalise_opt(buff)))
if (!(srv->name = canonicalise_opt(daemon->namebuff)))
die(_("bad srv-host name %s after domain appended"), srv->name, EC_MISC);
}
}
+50
View File
@@ -1027,3 +1027,53 @@ void free_real(const char *func, unsigned int line, void *ptr)
free(ptr);
}
}
/* get lines from f, expand buffer as required. Buffer is freed when
EOF reached and we return zero. */
int get_line_alloc(FILE *f, char **buffp, size_t *sizep)
{
char c;
size_t cnt = 0;
char *buff = *buffp;
while (1) {
c = getc(f);
if (cnt == *sizep)
{
void *new;
if ((new = whine_realloc(*buffp, cnt + 1024)))
{
buff = *buffp = new;
*sizep = cnt + 1024;
}
else
{
/* allocation failed, ignore line. Whine_realloc will have complained. */
while (c != '\n' && c != EOF)
c = getc(f);
cnt = 0;
continue;
}
}
buff[cnt] = 0;
if (c == '\n')
return 1;
if (c == EOF) /* handle last line with no '\n' */
{
/* handle last line without '\n' */
if (cnt != 0)
return 1;
free(buff);
return 0;
}
buff[cnt++] = c;
}
}