1 /***
2 *mbscat_s_l.c - Concatenate one string to another (MBCS)
3 *
4 * Copyright (c) Microsoft Corporation. All rights reserved.
5 *
6 *Purpose:
7 * Concatenate one string to another (MBCS)
8 *
9 *******************************************************************************/
10 #ifndef _MBCS
11 #error This file should only be compiled with _MBCS defined
12 #endif
13
14 #include <corecrt_internal_mbstring.h>
15 #include <corecrt_internal_securecrt.h>
16
17
18
_mbscat_s_l(unsigned char * _Dst,size_t _SizeInBytes,const unsigned char * _Src,_LOCALE_ARG_DECL)19 errno_t __cdecl _mbscat_s_l(unsigned char *_Dst, size_t _SizeInBytes, const unsigned char *_Src, _LOCALE_ARG_DECL)
20 {
21 unsigned char *p;
22 size_t available;
23 BOOL fFoundInvalidMBC, fIsLeadPrefix;
24
25 /* validation section */
26 _VALIDATE_STRING(_Dst, _SizeInBytes);
27 _VALIDATE_POINTER_RESET_STRING(_Src, _Dst, _SizeInBytes);
28
29 _LOCALE_UPDATE;
30 if (_LOCALE_SHORTCUT_TEST)
31 {
32 return strcat_s((char *)_Dst, _SizeInBytes, (const char *)_Src);
33 }
34
35 fFoundInvalidMBC = FALSE;
36 p = _Dst;
37 available = _SizeInBytes;
38 while (available > 0 && *p != 0)
39 {
40 p++;
41 available--;
42 }
43
44 /*
45 * Ran out of room while looking for end of dst string.
46 * p points 1 past end of buffer. We can't look past
47 * end of buffer so can't tell if dst ended with an
48 * invalid mbc.
49 */
50
51 if (available == 0)
52 {
53 _RESET_STRING(_Dst, _SizeInBytes);
54 _RETURN_DEST_NOT_NULL_TERMINATED(_Dst, _SizeInBytes);
55 }
56
57 /*
58 * Otherwise we have space available, p points at null that lies
59 * within _SizeInBytes, so available > 0. Check if dst ended with
60 * an invalid MBC (lead+null), if so then clear that lead byte,
61 * move the pointer back one and increase available by one.
62 */
63
64 _ISMBBLEADPREFIX(fIsLeadPrefix, _Dst, p-1);
65 if (fIsLeadPrefix)
66 {
67 fFoundInvalidMBC = TRUE;
68 p--;
69 *p = 0;
70 available++;
71 }
72
73 /* Append dst to src. */
74
75 while ((*p++ = *_Src++) != 0 && --available > 0)
76 {
77 }
78
79 /*
80 * We've run out of room in the destination before finding null in the src.
81 * It could be that the src was terminated with an invalid mbc (lead+null).
82 * In that case its ok to clear the copied lead byte and return mbcs_error.
83 */
84
85 if (available == 0)
86 {
87 if (*_Src == 0)
88 {
89 _ISMBBLEADPREFIX(fIsLeadPrefix, _Dst, p-1);
90 if (fIsLeadPrefix)
91 {
92 /* the source string ended with a lead byte: we remove it */
93 p[-1] = 0;
94 _RETURN_MBCS_ERROR;
95 }
96 }
97 _RESET_STRING(_Dst, _SizeInBytes);
98 _RETURN_BUFFER_TOO_SMALL(_Dst, _SizeInBytes);
99 }
100
101 /*
102 * If the src string ended with an invalid mbc (lead+null) then clear the
103 * lead byte.
104 */
105
106 _ISMBBLEADPREFIX(fIsLeadPrefix, _Dst, p-2);
107 if (fIsLeadPrefix)
108 {
109 p[-2] = 0;
110 available++;
111 fFoundInvalidMBC = TRUE;
112 }
113
114 _FILL_STRING(_Dst, _SizeInBytes, _SizeInBytes - available + 1);
115
116 if (fFoundInvalidMBC)
117 {
118 _RETURN_MBCS_ERROR;
119 }
120
121 _RETURN_NO_ERROR;
122 }
123