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