From owner-svn-src-all@FreeBSD.ORG Sun Jul 27 22:54:16 2014 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 8D04B8A7; Sun, 27 Jul 2014 22:54:16 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 6E5A22128; Sun, 27 Jul 2014 22:54:16 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id s6RMsG7t049566; Sun, 27 Jul 2014 22:54:16 GMT (envelope-from bapt@svn.freebsd.org) Received: (from bapt@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id s6RMsE4E049551; Sun, 27 Jul 2014 22:54:14 GMT (envelope-from bapt@svn.freebsd.org) Message-Id: <201407272254.s6RMsE4E049551@svn.freebsd.org> From: Baptiste Daroussin Date: Sun, 27 Jul 2014 22:54:14 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r269162 - in head/usr.bin/m4: . lib X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 27 Jul 2014 22:54:16 -0000 Author: bapt Date: Sun Jul 27 22:54:13 2014 New Revision: 269162 URL: http://svnweb.freebsd.org/changeset/base/269162 Log: Sync with OpenBSD This brings: - check for integer overflows in custom allocs - fix potential integer overflows in memory allocation - annotate regexp error messages with source string - better error handling in mkstemp/unlink/fdopen logic Added: head/usr.bin/m4/lib/ohash.c (contents, props changed) Deleted: head/usr.bin/m4/lib/ohash_create_entry.c head/usr.bin/m4/lib/ohash_delete.c head/usr.bin/m4/lib/ohash_do.c head/usr.bin/m4/lib/ohash_entries.c head/usr.bin/m4/lib/ohash_enum.c head/usr.bin/m4/lib/ohash_init.c head/usr.bin/m4/lib/ohash_interval.c head/usr.bin/m4/lib/ohash_lookup_interval.c head/usr.bin/m4/lib/ohash_lookup_memory.c head/usr.bin/m4/lib/ohash_qlookup.c head/usr.bin/m4/lib/ohash_qlookupi.c Modified: head/usr.bin/m4/Makefile head/usr.bin/m4/eval.c head/usr.bin/m4/extern.h head/usr.bin/m4/gnum4.c head/usr.bin/m4/lib/ohash.h head/usr.bin/m4/lib/ohash_init.3 head/usr.bin/m4/lib/ohash_interval.3 head/usr.bin/m4/look.c head/usr.bin/m4/m4.1 head/usr.bin/m4/main.c head/usr.bin/m4/misc.c Modified: head/usr.bin/m4/Makefile ============================================================================== --- head/usr.bin/m4/Makefile Sun Jul 27 20:55:47 2014 (r269161) +++ head/usr.bin/m4/Makefile Sun Jul 27 22:54:13 2014 (r269162) @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.10 2002/04/26 13:13:41 espie Exp $ +# $OpenBSD: Makefile,v 1.13 2014/05/12 19:11:19 espie Exp $ # $FreeBSD$ # -DEXTENDED @@ -15,10 +15,7 @@ NO_WMISSING_VARIABLE_DECLARATIONS= SRCS= eval.c expr.c look.c main.c misc.c gnum4.c trace.c parser.y tokenizer.l .PATH: ${.CURDIR}/lib -SRCS+= ohash_create_entry.c ohash_delete.c ohash_do.c ohash_entries.c \ - ohash_enum.c ohash_init.c ohash_int.h ohash_interval.c \ - ohash_lookup_interval.c ohash_lookup_memory.c ohash_qlookup.c \ - ohash_qlookupi.c +SRCS+= ohash.c tokenizer.o: parser.h Modified: head/usr.bin/m4/eval.c ============================================================================== --- head/usr.bin/m4/eval.c Sun Jul 27 20:55:47 2014 (r269161) +++ head/usr.bin/m4/eval.c Sun Jul 27 22:54:13 2014 (r269162) @@ -1,4 +1,4 @@ -/* $OpenBSD: eval.c,v 1.70 2012/04/12 17:00:11 espie Exp $ */ +/* $OpenBSD: eval.c,v 1.73 2014/07/11 21:04:17 espie Exp $ */ /* $NetBSD: eval.c,v 1.7 1996/11/10 21:21:29 pk Exp $ */ /* @@ -267,7 +267,7 @@ expand_builtin(const char *argv[], int a doesyscmd(argv[2]); break; case INCLTYPE: - if (argc > 2) + if (argc > 2) { if (!doincl(argv[2])) { if (mimic_gnu) { warn("%s at line %lu: include(%s)", @@ -277,6 +277,7 @@ expand_builtin(const char *argv[], int a err(1, "%s at line %lu: include(%s)", CURRENT_NAME, CURRENT_LINE, argv[2]); } + } break; case SINCTYPE: @@ -794,7 +795,7 @@ dom4wrap(const char *text) maxwraps = 16; else maxwraps *= 2; - m4wraps = xrealloc(m4wraps, maxwraps * sizeof(*m4wraps), + m4wraps = xreallocarray(m4wraps, maxwraps, sizeof(*m4wraps), "too many m4wraps"); } m4wraps[wrapindex++] = xstrdup(text); @@ -821,11 +822,10 @@ dodiv(int n) if (outfile[n] == NULL) { char fname[] = _PATH_DIVNAME; - if ((fd = mkstemp(fname)) < 0 || - (outfile[n] = fdopen(fd, "w+")) == NULL) - err(1, "%s: cannot divert", fname); - if (unlink(fname) == -1) - err(1, "%s: cannot unlink", fname); + if ((fd = mkstemp(fname)) < 0 || + unlink(fname) == -1 || + (outfile[n] = fdopen(fd, "w+")) == NULL) + err(1, "%s: cannot divert", fname); } active = outfile[n]; } Modified: head/usr.bin/m4/extern.h ============================================================================== --- head/usr.bin/m4/extern.h Sun Jul 27 20:55:47 2014 (r269161) +++ head/usr.bin/m4/extern.h Sun Jul 27 22:54:13 2014 (r269162) @@ -1,4 +1,4 @@ -/* $OpenBSD: extern.h,v 1.52 2012/04/12 17:00:11 espie Exp $ */ +/* $OpenBSD: extern.h,v 1.54 2014/05/12 19:11:19 espie Exp $ */ /* $NetBSD: extern.h,v 1.3 1996/01/13 23:25:24 pk Exp $ */ /*- @@ -104,8 +104,10 @@ extern void pbnumbase(int, int, int); extern void pbunsigned(unsigned long); extern void pbstr(const char *); extern void pushback(int); -extern void *xalloc(size_t, const char *fmt, ...); -extern void *xrealloc(void *, size_t, const char *fmt, ...); +extern void *xalloc(size_t, const char *, ...); +extern void *xcalloc(size_t, size_t, const char *, ...); +extern void *xrealloc(void *, size_t, const char *, ...); +extern void *xreallocarray(void *, size_t, size_t, const char *, ...); extern char *xstrdup(const char *); extern void usage(void); extern void resizedivs(int); Modified: head/usr.bin/m4/gnum4.c ============================================================================== --- head/usr.bin/m4/gnum4.c Sun Jul 27 20:55:47 2014 (r269161) +++ head/usr.bin/m4/gnum4.c Sun Jul 27 22:54:13 2014 (r269162) @@ -1,4 +1,4 @@ -/* $OpenBSD: gnum4.c,v 1.42 2011/11/06 12:25:43 espie Exp $ */ +/* $OpenBSD: gnum4.c,v 1.46 2014/07/10 14:12:31 espie Exp $ */ /* * Copyright (c) 1999 Marc Espie @@ -196,10 +196,12 @@ static void addchars(const char *, size_ static void addchar(int); static char *twiddle(const char *); static char *getstring(void); -static void exit_regerror(int, regex_t *); -static void do_subst(const char *, regex_t *, const char *, regmatch_t *); -static void do_regexpindex(const char *, regex_t *, regmatch_t *); -static void do_regexp(const char *, regex_t *, const char *, regmatch_t *); +static void exit_regerror(int, regex_t *, const char *); +static void do_subst(const char *, regex_t *, const char *, const char *, + regmatch_t *); +static void do_regexpindex(const char *, regex_t *, const char *, regmatch_t *); +static void do_regexp(const char *, regex_t *, const char *, const char *, + regmatch_t *); static void add_sub(int, const char *, regex_t *, regmatch_t *); static void add_replace(const char *, regex_t *, const char *, regmatch_t *); #define addconstantstring(s) addchars((s), sizeof(s)-1) @@ -243,7 +245,7 @@ getstring(void) static void -exit_regerror(int er, regex_t *re) +exit_regerror(int er, regex_t *re, const char *source) { size_t errlen; char *errbuf; @@ -252,7 +254,7 @@ exit_regerror(int er, regex_t *re) errbuf = xalloc(errlen, "malloc in regerror: %lu", (unsigned long)errlen); regerror(er, re, errbuf, errlen); - m4errx(1, "regular expression error: %s.", errbuf); + m4errx(1, "regular expression error in %s: %s.", source, errbuf); } static void @@ -296,7 +298,7 @@ add_replace(const char *string, regex_t p++; continue; } - if (isdigit(p[1])) { + if (isdigit((unsigned char)p[1])) { add_sub(*(++p) - '0', string, re, pm); continue; } @@ -306,7 +308,8 @@ add_replace(const char *string, regex_t } static void -do_subst(const char *string, regex_t *re, const char *replace, regmatch_t *pm) +do_subst(const char *string, regex_t *re, const char *source, + const char *replace, regmatch_t *pm) { int error; int flags = 0; @@ -341,12 +344,13 @@ do_subst(const char *string, regex_t *re string += pm[0].rm_eo; } if (error != REG_NOMATCH) - exit_regerror(error, re); + exit_regerror(error, re, source); pbstr(string); } static void -do_regexp(const char *string, regex_t *re, const char *replace, regmatch_t *pm) +do_regexp(const char *string, regex_t *re, const char *source, + const char *replace, regmatch_t *pm) { int error; @@ -358,12 +362,13 @@ do_regexp(const char *string, regex_t *r case REG_NOMATCH: break; default: - exit_regerror(error, re); + exit_regerror(error, re, source); } } static void -do_regexpindex(const char *string, regex_t *re, regmatch_t *pm) +do_regexpindex(const char *string, regex_t *re, const char *source, + regmatch_t *pm) { int error; @@ -375,7 +380,7 @@ do_regexpindex(const char *string, regex pbnum(-1); break; default: - exit_regerror(error, re); + exit_regerror(error, re, source); } } @@ -459,6 +464,7 @@ dopatsubst(const char *argv[], int argc) regex_t re; regmatch_t *pmatch; int mode = REG_EXTENDED; + const char *source; size_t l = strlen(argv[3]); if (!mimic_gnu || @@ -466,13 +472,14 @@ dopatsubst(const char *argv[], int argc) (l > 0 && argv[3][l-1] == '$')) mode |= REG_NEWLINE; - error = regcomp(&re, mimic_gnu ? twiddle(argv[3]) : argv[3], - mode); + source = mimic_gnu ? twiddle(argv[3]) : argv[3]; + error = regcomp(&re, source, mode); if (error != 0) - exit_regerror(error, &re); + exit_regerror(error, &re, source); - pmatch = xalloc(sizeof(regmatch_t) * (re.re_nsub+1), NULL); - do_subst(argv[2], &re, + pmatch = xreallocarray(NULL, re.re_nsub+1, sizeof(regmatch_t), + NULL); + do_subst(argv[2], &re, source, argc > 4 && argv[4] != NULL ? argv[4] : "", pmatch); free(pmatch); regfree(&re); @@ -486,6 +493,7 @@ doregexp(const char *argv[], int argc) int error; regex_t re; regmatch_t *pmatch; + const char *source; if (argc <= 3) { warnx("Too few arguments to regexp"); @@ -498,16 +506,16 @@ doregexp(const char *argv[], int argc) else pbstr(argv[4]); } - error = regcomp(&re, mimic_gnu ? twiddle(argv[3]) : argv[3], - REG_EXTENDED|REG_NEWLINE); + source = mimic_gnu ? twiddle(argv[3]) : argv[3]; + error = regcomp(&re, source, REG_EXTENDED|REG_NEWLINE); if (error != 0) - exit_regerror(error, &re); + exit_regerror(error, &re, source); - pmatch = xalloc(sizeof(regmatch_t) * (re.re_nsub+1), NULL); + pmatch = xreallocarray(NULL, re.re_nsub+1, sizeof(regmatch_t), NULL); if (argc == 4 || argv[4] == NULL) - do_regexpindex(argv[2], &re, pmatch); + do_regexpindex(argv[2], &re, source, pmatch); else - do_regexp(argv[2], &re, argv[4], pmatch); + do_regexp(argv[2], &re, source, argv[4], pmatch); free(pmatch); regfree(&re); } Added: head/usr.bin/m4/lib/ohash.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/usr.bin/m4/lib/ohash.c Sun Jul 27 22:54:13 2014 (r269162) @@ -0,0 +1,330 @@ +/* $OpenBSD: src/lib/libutil/ohash.c,v 1.1 2014/06/02 18:52:03 deraadt Exp $ */ + +/* Copyright (c) 1999, 2004 Marc Espie + * + * 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include "ohash.h" + +struct _ohash_record { + uint32_t hv; + const char *p; +}; + +#define DELETED ((const char *)h) +#define NONE (h->size) + +/* Don't bother changing the hash table if the change is small enough. */ +#define MINSIZE (1UL << 4) +#define MINDELETED 4 + +static void ohash_resize(struct ohash *); + + +/* This handles the common case of variable length keys, where the + * key is stored at the end of the record. + */ +void * +ohash_create_entry(struct ohash_info *i, const char *start, const char **end) +{ + char *p; + + if (!*end) + *end = start + strlen(start); + p = (i->alloc)(i->key_offset + (*end - start) + 1, i->data); + if (p) { + memcpy(p+i->key_offset, start, *end-start); + p[i->key_offset + (*end - start)] = '\0'; + } + return (void *)p; +} + +/* hash_delete only frees the hash structure. Use hash_first/hash_next + * to free entries as well. */ +void +ohash_delete(struct ohash *h) +{ + (h->info.free)(h->t, h->info.data); +#ifndef NDEBUG + h->t = NULL; +#endif +} + +static void +ohash_resize(struct ohash *h) +{ + struct _ohash_record *n; + size_t ns; + unsigned int j; + unsigned int i, incr; + + if (4 * h->deleted < h->total) { + if (h->size >= (UINT_MAX >> 1U)) + ns = UINT_MAX; + else + ns = h->size << 1U; + } else if (3 * h->deleted > 2 * h->total) + ns = h->size >> 1U; + else + ns = h->size; + if (ns < MINSIZE) + ns = MINSIZE; +#ifdef STATS_HASH + STAT_HASH_EXPAND++; + STAT_HASH_SIZE += ns - h->size; +#endif + + n = (h->info.calloc)(ns, sizeof(struct _ohash_record), h->info.data); + if (!n) + return; + + for (j = 0; j < h->size; j++) { + if (h->t[j].p != NULL && h->t[j].p != DELETED) { + i = h->t[j].hv % ns; + incr = ((h->t[j].hv % (ns - 2)) & ~1) + 1; + while (n[i].p != NULL) { + i += incr; + if (i >= ns) + i -= ns; + } + n[i].hv = h->t[j].hv; + n[i].p = h->t[j].p; + } + } + (h->info.free)(h->t, h->info.data); + h->t = n; + h->size = ns; + h->total -= h->deleted; + h->deleted = 0; +} + +void * +ohash_remove(struct ohash *h, unsigned int i) +{ + void *result = (void *)h->t[i].p; + + if (result == NULL || result == DELETED) + return NULL; + +#ifdef STATS_HASH + STAT_HASH_ENTRIES--; +#endif + h->t[i].p = DELETED; + h->deleted++; + if (h->deleted >= MINDELETED && 4 * h->deleted > h->total) + ohash_resize(h); + return result; +} + +void * +ohash_find(struct ohash *h, unsigned int i) +{ + if (h->t[i].p == DELETED) + return NULL; + else + return (void *)h->t[i].p; +} + +void * +ohash_insert(struct ohash *h, unsigned int i, void *p) +{ +#ifdef STATS_HASH + STAT_HASH_ENTRIES++; +#endif + if (h->t[i].p == DELETED) { + h->deleted--; + h->t[i].p = p; + } else { + h->t[i].p = p; + /* Arbitrary resize boundary. Tweak if not efficient enough. */ + if (++h->total * 4 > h->size * 3) + ohash_resize(h); + } + return p; +} + +unsigned int +ohash_entries(struct ohash *h) +{ + return h->total - h->deleted; +} + +void * +ohash_first(struct ohash *h, unsigned int *pos) +{ + *pos = 0; + return ohash_next(h, pos); +} + +void * +ohash_next(struct ohash *h, unsigned int *pos) +{ + for (; *pos < h->size; (*pos)++) + if (h->t[*pos].p != DELETED && h->t[*pos].p != NULL) + return (void *)h->t[(*pos)++].p; + return NULL; +} + +void +ohash_init(struct ohash *h, unsigned int size, struct ohash_info *info) +{ + h->size = 1UL << size; + if (h->size < MINSIZE) + h->size = MINSIZE; +#ifdef STATS_HASH + STAT_HASH_CREATION++; + STAT_HASH_SIZE += h->size; +#endif + /* Copy info so that caller may free it. */ + h->info.key_offset = info->key_offset; + h->info.calloc = info->calloc; + h->info.free = info->free; + h->info.alloc = info->alloc; + h->info.data = info->data; + h->t = (h->info.calloc)(h->size, sizeof(struct _ohash_record), + h->info.data); + h->total = h->deleted = 0; +} + +uint32_t +ohash_interval(const char *s, const char **e) +{ + uint32_t k; + + if (!*e) + *e = s + strlen(s); + if (s == *e) + k = 0; + else + k = *s++; + while (s != *e) + k = ((k << 2) | (k >> 30)) ^ *s++; + return k; +} + +unsigned int +ohash_lookup_interval(struct ohash *h, const char *start, const char *end, + uint32_t hv) +{ + unsigned int i, incr; + unsigned int empty; + +#ifdef STATS_HASH + STAT_HASH_LOOKUP++; +#endif + empty = NONE; + i = hv % h->size; + incr = ((hv % (h->size-2)) & ~1) + 1; + while (h->t[i].p != NULL) { +#ifdef STATS_HASH + STAT_HASH_LENGTH++; +#endif + if (h->t[i].p == DELETED) { + if (empty == NONE) + empty = i; + } else if (h->t[i].hv == hv && + strncmp(h->t[i].p+h->info.key_offset, start, + end - start) == 0 && + (h->t[i].p+h->info.key_offset)[end-start] == '\0') { + if (empty != NONE) { + h->t[empty].hv = hv; + h->t[empty].p = h->t[i].p; + h->t[i].p = DELETED; + return empty; + } else { +#ifdef STATS_HASH + STAT_HASH_POSITIVE++; +#endif + return i; + } + } + i += incr; + if (i >= h->size) + i -= h->size; + } + + /* Found an empty position. */ + if (empty != NONE) + i = empty; + h->t[i].hv = hv; + return i; +} + +unsigned int +ohash_lookup_memory(struct ohash *h, const char *k, size_t size, uint32_t hv) +{ + unsigned int i, incr; + unsigned int empty; + +#ifdef STATS_HASH + STAT_HASH_LOOKUP++; +#endif + empty = NONE; + i = hv % h->size; + incr = ((hv % (h->size-2)) & ~1) + 1; + while (h->t[i].p != NULL) { +#ifdef STATS_HASH + STAT_HASH_LENGTH++; +#endif + if (h->t[i].p == DELETED) { + if (empty == NONE) + empty = i; + } else if (h->t[i].hv == hv && + memcmp(h->t[i].p+h->info.key_offset, k, size) == 0) { + if (empty != NONE) { + h->t[empty].hv = hv; + h->t[empty].p = h->t[i].p; + h->t[i].p = DELETED; + return empty; + } else { +#ifdef STATS_HASH + STAT_HASH_POSITIVE++; +#endif + } return i; + } + i += incr; + if (i >= h->size) + i -= h->size; + } + + /* Found an empty position. */ + if (empty != NONE) + i = empty; + h->t[i].hv = hv; + return i; +} + +unsigned int +ohash_qlookup(struct ohash *h, const char *s) +{ + const char *e = NULL; + return ohash_qlookupi(h, s, &e); +} + +unsigned int +ohash_qlookupi(struct ohash *h, const char *s, const char **e) +{ + uint32_t hv; + + hv = ohash_interval(s, e); + return ohash_lookup_interval(h, s, *e, hv); +} Modified: head/usr.bin/m4/lib/ohash.h ============================================================================== --- head/usr.bin/m4/lib/ohash.h Sun Jul 27 20:55:47 2014 (r269161) +++ head/usr.bin/m4/lib/ohash.h Sun Jul 27 22:54:13 2014 (r269162) @@ -1,8 +1,4 @@ -#ifndef OHASH_H -#define OHASH_H -/* $OpenBSD: ohash.h,v 1.8 2005/12/29 18:54:47 jaredy Exp $ */ -/* ex:ts=8 sw=4: - */ +/* $OpenBSD: src/lib/libutil/ohash.h,v 1.2 2014/06/02 18:52:03 deraadt Exp $ */ /* Copyright (c) 1999, 2004 Marc Espie * @@ -21,21 +17,26 @@ * $FreeBSD$ */ +#ifndef OHASH_H +#define OHASH_H + /* Open hashing support. * Open hashing was chosen because it is much lighter than other hash * techniques, and more efficient in most cases. */ +/* user-visible data structure */ struct ohash_info { ptrdiff_t key_offset; void *data; /* user data */ - void *(*halloc)(size_t, void *); - void (*hfree)(void *, size_t, void *); + void *(*calloc)(size_t, size_t, void *); + void (*free)(void *, void *); void *(*alloc)(size_t, void *); }; struct _ohash_record; +/* private structure. It's there just so you can do a sizeof */ struct ohash { struct _ohash_record *t; struct ohash_info info; @@ -55,9 +56,10 @@ void ohash_init(struct ohash *, unsigned void ohash_delete(struct ohash *); unsigned int ohash_lookup_interval(struct ohash *, const char *, - const char *, u_int32_t); + const char *, uint32_t); unsigned int ohash_lookup_memory(struct ohash *, const char *, - size_t, u_int32_t); + size_t, uint32_t) + __attribute__ ((__bounded__(__string__,2,3))); void *ohash_find(struct ohash *, unsigned int); void *ohash_remove(struct ohash *, unsigned int); void *ohash_insert(struct ohash *, unsigned int, void *); @@ -66,10 +68,9 @@ void *ohash_next(struct ohash *, unsigne unsigned int ohash_entries(struct ohash *); void *ohash_create_entry(struct ohash_info *, const char *, const char **); -u_int32_t ohash_interval(const char *, const char **); +uint32_t ohash_interval(const char *, const char **); unsigned int ohash_qlookupi(struct ohash *, const char *, const char **); unsigned int ohash_qlookup(struct ohash *, const char *); __END_DECLS #endif - Modified: head/usr.bin/m4/lib/ohash_init.3 ============================================================================== --- head/usr.bin/m4/lib/ohash_init.3 Sun Jul 27 20:55:47 2014 (r269161) +++ head/usr.bin/m4/lib/ohash_init.3 Sun Jul 27 22:54:13 2014 (r269162) @@ -1,4 +1,4 @@ -.\" $OpenBSD: ohash_init.3,v 1.14 2007/05/31 19:19:30 jmc Exp $ +.\" $OpenBSD: ohash_init.3,v 1.2 2014/05/13 14:01:41 jmc Exp $ .\" Copyright (c) 1999 Marc Espie .\" .\" Permission to use, copy, modify, and distribute this software for any @@ -15,8 +15,8 @@ .\" .\" $FreeBSD$ .\" -.Dd $Mdocdate: May 31 2007 $ -.Dt OPEN_HASH 3 +.Dd May 12 2014 +.Dt OHASH_INIT 3 .Os .Sh NAME .Nm ohash_init , @@ -71,11 +71,46 @@ initializes the table to store roughly 2 .Fa size elements. .Fa info -holds the position of the key in each record, and two pointers to +is a pointer to a +.Fa struct ohash_info . +.Bd -literal -offset indent +struct ohash_info { + ptrdiff_t key_offset; + void *data; /* user data */ + void *(*calloc)(size_t, size_t, void *); + void (*free)(void *, void *); + void *(*alloc)(size_t, void *); +}; +.Ed +.Pp +The +.Va offset +field holds the position of the key in each record; +the +.Va calloc +and +.Va free +fields are pointers to .Xr calloc 3 and .Xr free 3 Ns -like -functions, to use for managing the table internal storage. +functions, used for managing the table internal storage; +the +.Va alloc +field is only used by the utility function +.Xr ohash_create_entry 3 . +.Pp +Each of these functions are called similarly to their standard counterpart, +but with an extra +.Ft void * +parameter corresponding to the content of the field +.Fa data , +which can be used to communicate specific information to the functions. +.Pp +.Fn ohash_init +stores a copy of those fields internally, so +.Fa info +can be reclaimed after initialization. .Pp .Fn ohash_delete frees storage internal to @@ -166,7 +201,7 @@ for (n = ohash_first(h, &i); n != NULL; points to an auxiliary unsigned integer used to record the current position in the ohash table. Those functions are safe to use even while entries are added to/removed -from the table, but in such a case they do not guarantee that new entries +from the table, but in such a case they don't guarantee that new entries will be returned. As a special case, they can safely be used to free elements in the table. .Pp @@ -179,7 +214,13 @@ Only .Fn ohash_remove and .Fn ohash_delete -may call the user-supplied memory functions. +may call the user-supplied memory functions: +.Bd -literal -offset indent +p = (*info->calloc)(n, sizeof_record, info->data); +/* copy data from old to p */ +(*info->free)(old, info->data); +.Ed +.Pp It is the responsibility of the user memory allocation code to verify that those calls did not fail. .Pp @@ -213,6 +254,7 @@ call. .Pp Multi-threaded applications should explicitly protect ohash table access. .Sh SEE ALSO +.Xr hcreate 3 , .Xr ohash_interval 3 .Rs .%A Donald E. Knuth Modified: head/usr.bin/m4/lib/ohash_interval.3 ============================================================================== --- head/usr.bin/m4/lib/ohash_interval.3 Sun Jul 27 20:55:47 2014 (r269161) +++ head/usr.bin/m4/lib/ohash_interval.3 Sun Jul 27 22:54:13 2014 (r269162) @@ -1,4 +1,4 @@ -.\" $OpenBSD: ohash_interval.3,v 1.11 2007/05/31 19:19:30 jmc Exp $ +.\" $OpenBSD: ohash_interval.3,v 1.1 2014/05/12 19:09:00 espie Exp $ .\" Copyright (c) 2001 Marc Espie .\" .\" Permission to use, copy, modify, and distribute this software for any @@ -15,8 +15,8 @@ .\" .\" $FreeBSD$ .\" -.Dd $Mdocdate: May 31 2007 $ -.Dt OPEN_HASH_HELPER 3 +.Dd June 5 2013 +.Dt OHASH_INTERVAL 3 .Os .Sh NAME .Nm ohash_interval , @@ -68,7 +68,10 @@ the alloc field of .Fa info should point to a .Xr malloc 3 Ns -like -function to allocate the storage. +function to allocate the storage: +.Bd -literal -offset indent +p = (*info->alloc)(sz, info->data); +.Ed .Pp .Fn ohash_qlookupi is a wrapper function that simply calls Modified: head/usr.bin/m4/look.c ============================================================================== --- head/usr.bin/m4/look.c Sun Jul 27 20:55:47 2014 (r269161) +++ head/usr.bin/m4/look.c Sun Jul 27 22:54:13 2014 (r269162) @@ -1,4 +1,4 @@ -/* $OpenBSD: look.c,v 1.22 2010/09/07 19:58:09 marco Exp $ */ +/* $OpenBSD: look.c,v 1.23 2014/05/12 19:11:19 espie Exp $ */ /* * Copyright (c) 1989, 1993 @@ -51,36 +51,34 @@ __FBSDID("$FreeBSD$"); #include "stdd.h" #include "extern.h" -static void *hash_alloc(size_t, void *); -static void hash_free(void *, size_t, void *); +static void *hash_calloc(size_t, size_t, void *); +static void hash_free(void *, void *); static void *element_alloc(size_t, void *); static void setup_definition(struct macro_definition *, const char *, const char *); static struct ohash_info macro_info = { offsetof(struct ndblock, name), - NULL, hash_alloc, hash_free, element_alloc }; + NULL, hash_calloc, hash_free, element_alloc }; struct ohash macros; /* Support routines for hash tables. */ void * -hash_alloc(size_t s, __unused void *u) +hash_calloc(size_t n, size_t s, void *u __unused) { - void *storage = xalloc(s, "hash alloc"); - if (storage) - memset(storage, 0, s); + void *storage = xcalloc(n, s, "hash alloc"); return storage; } void -hash_free(void *p, __unused size_t s, __unused void *u) +hash_free(void *p, void *u __unused) { free(p); } void * -element_alloc(size_t s, __unused void *u) +element_alloc(size_t s, void *u __unused) { return xalloc(s, "element alloc"); } Modified: head/usr.bin/m4/m4.1 ============================================================================== --- head/usr.bin/m4/m4.1 Sun Jul 27 20:55:47 2014 (r269161) +++ head/usr.bin/m4/m4.1 Sun Jul 27 22:54:13 2014 (r269162) @@ -1,5 +1,5 @@ .\" $NetBSD: m4.1,v 1.23 2012/04/08 22:00:39 wiz Exp $ -.\" @(#) $OpenBSD: m4.1,v 1.59 2010/10/21 13:20:51 jmc Exp $ +.\" @(#) $OpenBSD: m4.1,v 1.62 2014/04/14 07:00:47 jmc Exp $ .\" .\" Copyright (c) 1989, 1993 .\" The Regents of the University of California. All rights reserved. @@ -33,7 +33,7 @@ .\" .\" $FreeBSD$ .\" -.Dd October 21, 2010 +.Dd January 12 2014 $ .Dt M4 1 .Os .Sh NAME @@ -88,9 +88,7 @@ In arguments to macros, leading unquoted .Pq Sq \en characters are ignored. To quote strings, use left and right single quotes -.Po e.g.,\ \& -.Sq "\ this is a string with a leading space" -.Pc . +.Pq e.g., Sq \ \&this is a string with a leading space . You can change the quote characters with the .Ic changequote built-in macro. @@ -258,15 +256,17 @@ Prints the first argument on the standar Passes its first argument to a shell and returns the shell's standard output. Note that the shell shares its standard input and standard error with .Nm . -.It Fn eval expr +.It Fn eval expr[,radix[,minimum]] Computes the first argument as an arithmetic expression using 32-bit arithmetic. Operators are the standard C ternary, arithmetic, logical, shift, relational, bitwise, and parentheses operators. You can specify octal, decimal, and hexadecimal numbers as in C. -The second argument (if any) -specifies the radix for the result and the third argument (if any) +The optional second argument +.Fa radix +specifies the radix for the result and the optional third argument +.Fa minimum specifies the minimum number of digits in the result. .It Fn expr expr This is an alias for @@ -441,12 +441,12 @@ macro can modify the exit status. .Sh STANDARDS The .Nm -utility is mostly compliant with the +utility is compliant with the .St -p1003.1-2008 specification. .Pp The flags -.Op Fl dgIot +.Op Fl dgIPot and the macros .Ic builtin , .Ic esyscmd , @@ -467,9 +467,13 @@ are extensions to that specification. is not supposed to be a synonym for .Ic mkstemp , but instead to be an insecure temporary file name creation function. -The change causes no known compatibility issues. +It is marked by +.St -p1003.1-2008 +as being obsolescent and should not be used if portability is a concern. .Pp -The output format of tracing and of +The output format of +.Ic traceon +and .Ic dumpdef are not specified in any standard, are likely to change and should not be relied upon. Modified: head/usr.bin/m4/main.c ============================================================================== --- head/usr.bin/m4/main.c Sun Jul 27 20:55:47 2014 (r269161) +++ head/usr.bin/m4/main.c Sun Jul 27 22:54:13 2014 (r269162) @@ -1,4 +1,4 @@ -/* $OpenBSD: main.c,v 1.81 2012/04/12 17:00:11 espie Exp $ */ +/* $OpenBSD: main.c,v 1.83 2014/05/12 19:11:19 espie Exp $ */ /* $NetBSD: main.c,v 1.12 1997/02/08 23:54:49 cgd Exp $ */ /*- @@ -180,8 +180,8 @@ main(int argc, char *argv[]) initspaces(); STACKMAX = INITSTACKMAX; - mstack = (stae *)xalloc(sizeof(stae) * STACKMAX, NULL); - sstack = (char *)xalloc(STACKMAX, NULL); + mstack = xreallocarray(NULL, STACKMAX, sizeof(stae), NULL); + sstack = xalloc(STACKMAX, NULL); maxout = 0; outfile = NULL; @@ -415,7 +415,8 @@ macro(void) } } } else if (t == EOF) { - if (sp > -1 && ilevel <= 0) { + if (!mimic_gnu /* you can puke right there */ + && sp > -1 && ilevel <= 0) { warnx( "unexpected end of input, unclosed parenthesis:"); dump_stack(paren, PARLEV); exit(1); @@ -625,7 +626,7 @@ static void enlarge_stack(void) { STACKMAX += STACKMAX/2; - mstack = xrealloc(mstack, sizeof(stae) * STACKMAX, + mstack = xreallocarray(mstack, STACKMAX, sizeof(stae), "Evaluation stack overflow (%lu)", (unsigned long)STACKMAX); sstack = xrealloc(sstack, STACKMAX, Modified: head/usr.bin/m4/misc.c ============================================================================== --- head/usr.bin/m4/misc.c Sun Jul 27 20:55:47 2014 (r269161) +++ head/usr.bin/m4/misc.c Sun Jul 27 22:54:13 2014 (r269162) @@ -1,4 +1,4 @@ -/* $OpenBSD: misc.c,v 1.42 2010/09/07 19:58:09 marco Exp $ */ +/* $OpenBSD: misc.c,v 1.44 2014/05/12 19:11:19 espie Exp $ */ /* $NetBSD: misc.c,v 1.6 1995/09/28 05:37:41 tls Exp $ */ /* @@ -32,6 +32,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ + #include __FBSDID("$FreeBSD$"); @@ -40,6 +41,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -165,7 +167,7 @@ initspaces(void) strspace = xalloc(strsize+1, NULL); ep = strspace; endest = strspace+strsize; - buf = (unsigned char *)xalloc(bufsize, NULL); + buf = xalloc(bufsize, NULL); bufbase = buf; bp = buf; endpbb = buf + bufsize; @@ -239,7 +241,7 @@ getdiv(int n) } void -onintr(__unused int signo) +onintr(int signo __unused) { #define intrmessage "m4: interrupted.\n" write(STDERR_FILENO, intrmessage, sizeof(intrmessage)-1); @@ -263,7 +265,7 @@ killdiv(void) extern char *__progname; void *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***