1*72af5a45SBill Sommerfeld /*
2*72af5a45SBill Sommerfeld * This file and its contents are supplied under the terms of the
3*72af5a45SBill Sommerfeld * Common Development and Distribution License ("CDDL"), version 1.0.
4*72af5a45SBill Sommerfeld * You may only use this file in accordance with the terms of version
5*72af5a45SBill Sommerfeld * 1.0 of the CDDL.
6*72af5a45SBill Sommerfeld *
7*72af5a45SBill Sommerfeld * A full copy of the text of the CDDL should have accompanied this
8*72af5a45SBill Sommerfeld * source. A copy of the CDDL is also available via the Internet at
9*72af5a45SBill Sommerfeld * http://www.illumos.org/license/CDDL.
10*72af5a45SBill Sommerfeld */
11*72af5a45SBill Sommerfeld
12*72af5a45SBill Sommerfeld /*
13*72af5a45SBill Sommerfeld * Copyright 2024 Bill Sommerfeld <sommerfeld@hamachi.org>
14*72af5a45SBill Sommerfeld */
15*72af5a45SBill Sommerfeld
16*72af5a45SBill Sommerfeld /*
17*72af5a45SBill Sommerfeld * Regression test for illumos bug #16352: verify that strftime behaves
18*72af5a45SBill Sommerfeld * properly if the buffer length is overly large.
19*72af5a45SBill Sommerfeld */
20*72af5a45SBill Sommerfeld
21*72af5a45SBill Sommerfeld #include <limits.h>
22*72af5a45SBill Sommerfeld #include <stdio.h>
23*72af5a45SBill Sommerfeld #include <stdlib.h>
24*72af5a45SBill Sommerfeld #include <string.h>
25*72af5a45SBill Sommerfeld #include <time.h>
26*72af5a45SBill Sommerfeld
27*72af5a45SBill Sommerfeld static int status = EXIT_SUCCESS;
28*72af5a45SBill Sommerfeld
29*72af5a45SBill Sommerfeld static const char expected_buf[] = "2024 04 23";
30*72af5a45SBill Sommerfeld static int expected_ret = 10;
31*72af5a45SBill Sommerfeld
32*72af5a45SBill Sommerfeld static void
check_results(const char * name,int ret,const char * buf)33*72af5a45SBill Sommerfeld check_results(const char *name, int ret, const char *buf)
34*72af5a45SBill Sommerfeld {
35*72af5a45SBill Sommerfeld if (ret == 0) {
36*72af5a45SBill Sommerfeld fprintf(stderr, "TEST FAILED: %s returned 0\n", name);
37*72af5a45SBill Sommerfeld status = EXIT_FAILURE;
38*72af5a45SBill Sommerfeld }
39*72af5a45SBill Sommerfeld
40*72af5a45SBill Sommerfeld if (ret != 10) {
41*72af5a45SBill Sommerfeld fprintf(stderr, "TEST FAILED: %s length %d (expected %d)\n",
42*72af5a45SBill Sommerfeld name, ret, expected_ret);
43*72af5a45SBill Sommerfeld status = EXIT_FAILURE;
44*72af5a45SBill Sommerfeld }
45*72af5a45SBill Sommerfeld
46*72af5a45SBill Sommerfeld if (strcmp(buf, expected_buf) != 0) {
47*72af5a45SBill Sommerfeld fprintf(stderr, "TEST FAILED: %s contents [%s]"
48*72af5a45SBill Sommerfeld " (expected [%s])\n", name, buf, expected_buf);
49*72af5a45SBill Sommerfeld status = EXIT_FAILURE;
50*72af5a45SBill Sommerfeld }
51*72af5a45SBill Sommerfeld }
52*72af5a45SBill Sommerfeld
53*72af5a45SBill Sommerfeld int
main(void)54*72af5a45SBill Sommerfeld main(void)
55*72af5a45SBill Sommerfeld {
56*72af5a45SBill Sommerfeld int ret;
57*72af5a45SBill Sommerfeld struct tm t;
58*72af5a45SBill Sommerfeld char buf[1024];
59*72af5a45SBill Sommerfeld
60*72af5a45SBill Sommerfeld memset(&t, 0, sizeof (t));
61*72af5a45SBill Sommerfeld t.tm_year = 124;
62*72af5a45SBill Sommerfeld t.tm_mon = 3;
63*72af5a45SBill Sommerfeld t.tm_mday = 23;
64*72af5a45SBill Sommerfeld
65*72af5a45SBill Sommerfeld /*
66*72af5a45SBill Sommerfeld * Test that ascftime() behaves properly; ascftime calls
67*72af5a45SBill Sommerfeld * strftime(buf, LONG_MAX, format, t). For an unfixed libc,
68*72af5a45SBill Sommerfeld * this will fail if buf lies above the midpoint of the
69*72af5a45SBill Sommerfeld * process address space, as the computation of buf + len
70*72af5a45SBill Sommerfeld * overflows and wraps around.
71*72af5a45SBill Sommerfeld */
72*72af5a45SBill Sommerfeld ret = ascftime(buf, "%Y %m %d", &t);
73*72af5a45SBill Sommerfeld check_results("ascftime", ret, buf);
74*72af5a45SBill Sommerfeld
75*72af5a45SBill Sommerfeld /*
76*72af5a45SBill Sommerfeld * Repeat test with strftime passed the maximum possible length.
77*72af5a45SBill Sommerfeld * This will wrap around as long as buf is not NULL, letting us
78*72af5a45SBill Sommerfeld * exercise the fix even if the user address space is restricted
79*72af5a45SBill Sommerfeld * in some way.
80*72af5a45SBill Sommerfeld */
81*72af5a45SBill Sommerfeld ret = strftime(buf, ULONG_MAX, "%Y %m %d", &t);
82*72af5a45SBill Sommerfeld check_results("strftime", ret, buf);
83*72af5a45SBill Sommerfeld
84*72af5a45SBill Sommerfeld if (status == EXIT_SUCCESS) {
85*72af5a45SBill Sommerfeld (void) printf("TEST PASSED: observed expected output\n");
86*72af5a45SBill Sommerfeld }
87*72af5a45SBill Sommerfeld printf("NOTE: buffer is %p\n", buf);
88*72af5a45SBill Sommerfeld return (status);
89*72af5a45SBill Sommerfeld }
90