1 /* strcpy_s( char *, rsize_t, const char * )
2
3 This file is part of the Public Domain C Library (PDCLib).
4 Permission is granted to use, modify, and / or redistribute at will.
5 */
6
7 #define __STDC_WANT_LIB_EXT1__ 1
8 #include <string.h>
9 #include <stdint.h>
10 #include <stdlib.h>
11
12 #ifndef REGTEST
13
strcpy_s(char * _PDCLIB_restrict s1,rsize_t s1max,const char * _PDCLIB_restrict s2)14 errno_t strcpy_s( char * _PDCLIB_restrict s1, rsize_t s1max, const char * _PDCLIB_restrict s2 )
15 {
16 char * dest = s1;
17 const char * src = s2;
18
19 if ( s1 != NULL && s2 != NULL && s1max <= RSIZE_MAX && s1max != 0 )
20 {
21 while ( s1max-- )
22 {
23 if ( dest == s2 || src == s1 )
24 {
25 goto runtime_constraint_violation;
26 }
27
28 if ( ( *dest++ = *src++ ) == '\0' )
29 {
30 return 0;
31 }
32 }
33 }
34
35 runtime_constraint_violation:
36
37 if ( s1 != NULL && s1max > 0 && s1max <= RSIZE_MAX )
38 {
39 s1[0] = '\0';
40 }
41
42 _PDCLIB_constraint_handler( _PDCLIB_CONSTRAINT_VIOLATION( _PDCLIB_EINVAL ) );
43 return _PDCLIB_EINVAL;
44 }
45
46 #endif
47
48 #ifdef TEST
49
50 #include "_PDCLIB_test.h"
51
52 #if ! defined( REGTEST ) || defined( __STDC_LIB_EXT1__ )
53
54 static int HANDLER_CALLS = 0;
55
test_handler(const char * _PDCLIB_restrict msg,void * _PDCLIB_restrict ptr,errno_t error)56 static void test_handler( const char * _PDCLIB_restrict msg, void * _PDCLIB_restrict ptr, errno_t error )
57 {
58 ++HANDLER_CALLS;
59 }
60
61 #endif
62
main(void)63 int main( void )
64 {
65 #if ! defined( REGTEST ) || defined( __STDC_LIB_EXT1__ )
66 char s[] = "xxxxx";
67 set_constraint_handler_s( test_handler );
68
69 TESTCASE( strcpy_s( s, 6, "" ) == 0 );
70 TESTCASE( s[0] == '\0' );
71 TESTCASE( s[1] == 'x' );
72 TESTCASE( strcpy_s( s, 6, abcde ) == 0 );
73 TESTCASE( s[0] == 'a' );
74 TESTCASE( s[4] == 'e' );
75 TESTCASE( s[5] == '\0' );
76
77 /* Overrun. */
78 TESTCASE( strcpy_s( s, 6, "abcdef" ) != 0 );
79
80 /* Overlapping. */
81 TESTCASE( strcpy_s( s, 3, s + 2 ) != 0 );
82 TESTCASE( strcpy_s( s + 2, 3, s ) != 0 );
83
84 TESTCASE( HANDLER_CALLS == 3 );
85 #endif
86 return TEST_RESULTS;
87 }
88
89 #endif
90