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