summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--regress/lib/libc/Makefile4
-rw-r--r--regress/lib/libc/mkstemp/Makefile19
-rw-r--r--regress/lib/libc/mkstemp/mkstemp_test.c95
3 files changed, 116 insertions, 2 deletions
diff --git a/regress/lib/libc/Makefile b/regress/lib/libc/Makefile
index 3c24e3f6341..ddbb9505fe6 100644
--- a/regress/lib/libc/Makefile
+++ b/regress/lib/libc/Makefile
@@ -1,10 +1,10 @@
-# $OpenBSD: Makefile,v 1.30 2009/11/21 09:56:10 guenther Exp $
+# $OpenBSD: Makefile,v 1.31 2010/02/11 07:35:38 guenther Exp $
SUBDIR+= _setjmp alloca atexit basename cxa-atexit db dirname fnmatch
SUBDIR+= fpclassify getaddrinfo getcap getopt_long glob hsearch longjmp
SUBDIR+= locale malloc netdb popen printf regex setjmp setjmp-signal
SUBDIR+= sigreturn sigsetjmp sprintf strerror strtod strtonum telldir time vis
-SUBDIR+= orientation stdio_threading
+SUBDIR+= orientation stdio_threading mkstemp
.if (${MACHINE_ARCH} != "vax")
SUBDIR+= ieeefp
diff --git a/regress/lib/libc/mkstemp/Makefile b/regress/lib/libc/mkstemp/Makefile
new file mode 100644
index 00000000000..dc7eb281a9f
--- /dev/null
+++ b/regress/lib/libc/mkstemp/Makefile
@@ -0,0 +1,19 @@
+# $OpenBSD: Makefile,v 1.1 2010/02/11 07:35:38 guenther Exp $
+
+PROG=mkstemp_test
+CLEANFILES+= ; rm -rf output
+
+O = output
+
+# The ktrace/kdump/perl combo verifies that all open() calls that
+# were passed O_CREAT were also passed O_EXCL
+run-regress-${PROG}: ${PROG}
+ mkdir -p $O && cd $O && ktrace ../${PROG}
+ cd $O && kdump | perl -mFcntl -nl \
+ -e '/ open\([^,]*,([^,]+)/ or next;' \
+ -e '$$f = oct($$1);' \
+ -e 'if ($$f & O_CREAT && !($$f & O_EXCL)) {' \
+ -e ' print "FAIL"; exit 1' \
+ -e '}'
+
+.include <bsd.regress.mk>
diff --git a/regress/lib/libc/mkstemp/mkstemp_test.c b/regress/lib/libc/mkstemp/mkstemp_test.c
new file mode 100644
index 00000000000..d8311cbf351
--- /dev/null
+++ b/regress/lib/libc/mkstemp/mkstemp_test.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2010 Philip Guenther <guenther@openbsd.org>
+ *
+ * Public domain.
+ *
+ * Verify that mkstemp() doesn't overrun or underrun the template buffer
+ * and that it can generate names that don't contain any X's
+ */
+
+#include <sys/param.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#define MAX_TEMPLATE_LEN 10
+#define MAX_TRIES 100
+
+long pg;
+
+void
+try(char *p, const char *prefix, int len)
+{
+ struct stat sb, fsb;
+ char *q;
+ size_t plen = strlen(prefix);
+ int tries, fd;
+
+ for (tries = 0; tries < MAX_TRIES; tries++) {
+ memcpy(p, prefix, plen);
+ memset(p + plen, 'X', len);
+ p[plen + len] = '\0';
+ fd = mkstemp(p);
+ if (fd < 0)
+ err(1, "mkstemp");
+ if (stat(p, &sb))
+ err(1, "stat(%s)", p);
+ if (fstat(fd, &fsb))
+ err(1, "fstat(%d==%s)", fd, p);
+ if (sb.st_dev != fsb.st_dev || sb.st_ino != fsb.st_ino)
+ errx(1, "stat mismatch");
+ close(fd);
+ for (q = p + plen; *q != 'X'; q++) {
+ if (*q == '\0') {
+ if (q != p + plen + len)
+ errx(1, "unexpected truncation");
+ return;
+ }
+ }
+ if (q >= p + plen + len)
+ errx(1, "overrun?");
+ }
+ errx(1, "exceeded MAX_TRIES");
+}
+
+int
+main(void)
+{
+ struct stat sb, fsb;
+ char cwd[MAXPATHLEN + 1];
+ char *p;
+ size_t clen;
+ int i;
+
+ pg = sysconf(_SC_PAGESIZE);
+ if (getcwd(cwd, sizeof cwd - 1) == NULL)
+ err(1, "getcwd");
+ clen = strlen(cwd);
+ cwd[clen++] = '/';
+ cwd[clen] = '\0';
+ p = mmap(NULL, pg * 3, PROT_READ | PROT_WRITE, MAP_ANON, -1, 0);
+ if (p == NULL)
+ err(1, "mmap");
+ if (mprotect(p, pg, PROT_NONE) || mprotect(p + pg * 2, pg, PROT_NONE))
+ err(1, "mprotect");
+ p += pg;
+
+ i = MAX_TEMPLATE_LEN + 1;
+ while (i-- > 1) {
+ /* try first at the start of a page, no prefix */
+ try(p, "", i);
+ /* now at the end of the page, no prefix */
+ try(p + pg - i - 1, "", i);
+ /* start of the page, prefixed with the cwd */
+ try(p, cwd, i);
+ /* how about at the end of the page, prefixed with cwd? */
+ try(p + pg - i - 1 - clen, cwd, i);
+ }
+
+ return 0;
+}