You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

strcpy_s.c 14 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. /**
  2. * Copyright 2020 Huawei Technologies Co., Ltd
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #define SECUREC_INLINE_STR_LEN 1
  17. #define SECUREC_INLINE_DO_MEMCPY 1
  18. #include "securecutil.h"
  19. #if SECUREC_IN_KERNEL== 0
  20. #ifndef SECUREC_STRCOPY_THRESHOLD_SIZE
  21. #define SECUREC_STRCOPY_THRESHOLD_SIZE 32UL
  22. #endif
  23. /*
  24. * Determine whether the address is 8-byte aligned, use static to increase performance
  25. * return 0 is aligned
  26. */
  27. static int SecIsAddrAligned8(const void *addr, const void *zeroAddr)
  28. {
  29. return (int)(((size_t)((const char*)addr - (const char*)zeroAddr)) & 7); /* use 7 to check aligned 8 */
  30. }
  31. /* The purpose of converting to void is to clean up the alarm */
  32. #define SECUREC_SMALL_STR_COPY do { \
  33. if (SECUREC_ADDR_ALIGNED_8(strDest) && SECUREC_ADDR_ALIGNED_8(strSrc)) { \
  34. /* use struct assignment */ \
  35. switch (srcStrLen) { \
  36. case 1: \
  37. *(SecStrBuf1 *)(void *)strDest = *(const SecStrBuf1 *)(const void *)strSrc; \
  38. break; \
  39. case 2: \
  40. *(SecStrBuf2 *)(void *)strDest = *(const SecStrBuf2 *)(const void *)strSrc; \
  41. break; \
  42. case 3: \
  43. *(SecStrBuf3 *)(void *)strDest = *(const SecStrBuf3 *)(const void *)strSrc; \
  44. break; \
  45. case 4: \
  46. *(SecStrBuf4 *)(void *)strDest = *(const SecStrBuf4 *)(const void *)strSrc; \
  47. break; \
  48. case 5: \
  49. *(SecStrBuf5 *)(void *)strDest = *(const SecStrBuf5 *)(const void *)strSrc; \
  50. break; \
  51. case 6: \
  52. *(SecStrBuf6 *)(void *)strDest = *(const SecStrBuf6 *)(const void *)strSrc; \
  53. break; \
  54. case 7: \
  55. *(SecStrBuf7 *)(void *)strDest = *(const SecStrBuf7 *)(const void *)strSrc; \
  56. break; \
  57. case 8: \
  58. *(SecStrBuf8 *)(void *)strDest = *(const SecStrBuf8 *)(const void *)strSrc; \
  59. break; \
  60. case 9: \
  61. *(SecStrBuf9 *)(void *)strDest = *(const SecStrBuf9 *)(const void *)strSrc; \
  62. break; \
  63. case 10: \
  64. *(SecStrBuf10 *)(void *)strDest = *(const SecStrBuf10 *)(const void *)strSrc; \
  65. break; \
  66. case 11: \
  67. *(SecStrBuf11 *)(void *)strDest = *(const SecStrBuf11 *)(const void *)strSrc; \
  68. break; \
  69. case 12: \
  70. *(SecStrBuf12 *)(void *)strDest = *(const SecStrBuf12 *)(const void *)strSrc; \
  71. break; \
  72. case 13: \
  73. *(SecStrBuf13 *)(void *)strDest = *(const SecStrBuf13 *)(const void *)strSrc; \
  74. break; \
  75. case 14: \
  76. *(SecStrBuf14 *)(void *)strDest = *(const SecStrBuf14 *)(const void *)strSrc; \
  77. break; \
  78. case 15: \
  79. *(SecStrBuf15 *)(void *)strDest = *(const SecStrBuf15 *)(const void *)strSrc; \
  80. break; \
  81. case 16: \
  82. *(SecStrBuf16 *)(void *)strDest = *(const SecStrBuf16 *)(const void *)strSrc; \
  83. break; \
  84. case 17: \
  85. *(SecStrBuf17 *)(void *)strDest = *(const SecStrBuf17 *)(const void *)strSrc; \
  86. break; \
  87. case 18: \
  88. *(SecStrBuf18 *)(void *)strDest = *(const SecStrBuf18 *)(const void *)strSrc; \
  89. break; \
  90. case 19: \
  91. *(SecStrBuf19 *)(void *)strDest = *(const SecStrBuf19 *)(const void *)strSrc; \
  92. break; \
  93. case 20: \
  94. *(SecStrBuf20 *)(void *)strDest = *(const SecStrBuf20 *)(const void *)strSrc; \
  95. break; \
  96. case 21: \
  97. *(SecStrBuf21 *)(void *)strDest = *(const SecStrBuf21 *)(const void *)strSrc; \
  98. break; \
  99. case 22: \
  100. *(SecStrBuf22 *)(void *)strDest = *(const SecStrBuf22 *)(const void *)strSrc; \
  101. break; \
  102. case 23: \
  103. *(SecStrBuf23 *)(void *)strDest = *(const SecStrBuf23 *)(const void *)strSrc; \
  104. break; \
  105. case 24: \
  106. *(SecStrBuf24 *)(void *)strDest = *(const SecStrBuf24 *)(const void *)strSrc; \
  107. break; \
  108. case 25: \
  109. *(SecStrBuf25 *)(void *)strDest = *(const SecStrBuf25 *)(const void *)strSrc; \
  110. break; \
  111. case 26: \
  112. *(SecStrBuf26 *)(void *)strDest = *(const SecStrBuf26 *)(const void *)strSrc; \
  113. break; \
  114. case 27: \
  115. *(SecStrBuf27 *)(void *)strDest = *(const SecStrBuf27 *)(const void *)strSrc; \
  116. break; \
  117. case 28: \
  118. *(SecStrBuf28 *)(void *)strDest = *(const SecStrBuf28 *)(const void *)strSrc; \
  119. break; \
  120. case 29: \
  121. *(SecStrBuf29 *)(void *)strDest = *(const SecStrBuf29 *)(const void *)strSrc; \
  122. break; \
  123. case 30: \
  124. *(SecStrBuf30 *)(void *)strDest = *(const SecStrBuf30 *)(const void *)strSrc; \
  125. break; \
  126. case 31: \
  127. *(SecStrBuf31 *)(void *)strDest = *(const SecStrBuf31 *)(const void *)strSrc; \
  128. break; \
  129. case 32: \
  130. *(SecStrBuf32 *)(void *)strDest = *(const SecStrBuf32 *)(const void *)strSrc; \
  131. break; \
  132. default: \
  133. break; \
  134. } /* END switch */ \
  135. } else { \
  136. char *tmpStrDest = (char *)strDest; \
  137. const char *tmpStrSrc = (const char *)strSrc; \
  138. switch (srcStrLen) { \
  139. case 32: \
  140. *(tmpStrDest++) = *(tmpStrSrc++); \
  141. /* fall-through */ /* FALLTHRU */ \
  142. case 31: \
  143. *(tmpStrDest++) = *(tmpStrSrc++); \
  144. /* fall-through */ /* FALLTHRU */ \
  145. case 30: \
  146. *(tmpStrDest++) = *(tmpStrSrc++); \
  147. /* fall-through */ /* FALLTHRU */ \
  148. case 29: \
  149. *(tmpStrDest++) = *(tmpStrSrc++); \
  150. /* fall-through */ /* FALLTHRU */ \
  151. case 28: \
  152. *(tmpStrDest++) = *(tmpStrSrc++); \
  153. /* fall-through */ /* FALLTHRU */ \
  154. case 27: \
  155. *(tmpStrDest++) = *(tmpStrSrc++); \
  156. /* fall-through */ /* FALLTHRU */ \
  157. case 26: \
  158. *(tmpStrDest++) = *(tmpStrSrc++); \
  159. /* fall-through */ /* FALLTHRU */ \
  160. case 25: \
  161. *(tmpStrDest++) = *(tmpStrSrc++); \
  162. /* fall-through */ /* FALLTHRU */ \
  163. case 24: \
  164. *(tmpStrDest++) = *(tmpStrSrc++); \
  165. /* fall-through */ /* FALLTHRU */ \
  166. case 23: \
  167. *(tmpStrDest++) = *(tmpStrSrc++); \
  168. /* fall-through */ /* FALLTHRU */ \
  169. case 22: \
  170. *(tmpStrDest++) = *(tmpStrSrc++); \
  171. /* fall-through */ /* FALLTHRU */ \
  172. case 21: \
  173. *(tmpStrDest++) = *(tmpStrSrc++); \
  174. /* fall-through */ /* FALLTHRU */ \
  175. case 20: \
  176. *(tmpStrDest++) = *(tmpStrSrc++); \
  177. /* fall-through */ /* FALLTHRU */ \
  178. case 19: \
  179. *(tmpStrDest++) = *(tmpStrSrc++); \
  180. /* fall-through */ /* FALLTHRU */ \
  181. case 18: \
  182. *(tmpStrDest++) = *(tmpStrSrc++); \
  183. /* fall-through */ /* FALLTHRU */ \
  184. case 17: \
  185. *(tmpStrDest++) = *(tmpStrSrc++); \
  186. /* fall-through */ /* FALLTHRU */ \
  187. case 16: \
  188. *(tmpStrDest++) = *(tmpStrSrc++); \
  189. /* fall-through */ /* FALLTHRU */ \
  190. case 15: \
  191. *(tmpStrDest++) = *(tmpStrSrc++); \
  192. /* fall-through */ /* FALLTHRU */ \
  193. case 14: \
  194. *(tmpStrDest++) = *(tmpStrSrc++); \
  195. /* fall-through */ /* FALLTHRU */ \
  196. case 13: \
  197. *(tmpStrDest++) = *(tmpStrSrc++); \
  198. /* fall-through */ /* FALLTHRU */ \
  199. case 12: \
  200. *(tmpStrDest++) = *(tmpStrSrc++); \
  201. /* fall-through */ /* FALLTHRU */ \
  202. case 11: \
  203. *(tmpStrDest++) = *(tmpStrSrc++); \
  204. /* fall-through */ /* FALLTHRU */ \
  205. case 10: \
  206. *(tmpStrDest++) = *(tmpStrSrc++); \
  207. /* fall-through */ /* FALLTHRU */ \
  208. case 9: \
  209. *(tmpStrDest++) = *(tmpStrSrc++); \
  210. /* fall-through */ /* FALLTHRU */ \
  211. case 8: \
  212. *(tmpStrDest++) = *(tmpStrSrc++); \
  213. /* fall-through */ /* FALLTHRU */ \
  214. case 7: \
  215. *(tmpStrDest++) = *(tmpStrSrc++); \
  216. /* fall-through */ /* FALLTHRU */ \
  217. case 6: \
  218. *(tmpStrDest++) = *(tmpStrSrc++); \
  219. /* fall-through */ /* FALLTHRU */ \
  220. case 5: \
  221. *(tmpStrDest++) = *(tmpStrSrc++); \
  222. /* fall-through */ /* FALLTHRU */ \
  223. case 4: \
  224. *(tmpStrDest++) = *(tmpStrSrc++); \
  225. /* fall-through */ /* FALLTHRU */ \
  226. case 3: \
  227. *(tmpStrDest++) = *(tmpStrSrc++); \
  228. /* fall-through */ /* FALLTHRU */ \
  229. case 2: \
  230. *(tmpStrDest++) = *(tmpStrSrc++); \
  231. /* fall-through */ /* FALLTHRU */ \
  232. case 1: \
  233. *(tmpStrDest++) = *(tmpStrSrc++); \
  234. /* fall-through */ /* FALLTHRU */ \
  235. default: \
  236. break; \
  237. } \
  238. } \
  239. } SECUREC_WHILE_ZERO
  240. #endif
  241. /*
  242. * Check Src Range
  243. */
  244. static errno_t CheckSrcRange(char *strDest, size_t destMax, const char *strSrc)
  245. {
  246. size_t tmpDestMax = destMax;
  247. const char *tmpSrc = strSrc;
  248. /* use destMax as boundary checker and destMax must be greater than zero */
  249. while (*(tmpSrc) != '\0' && tmpDestMax > 0) {
  250. ++tmpSrc;
  251. --tmpDestMax;
  252. }
  253. if (tmpDestMax == 0) {
  254. strDest[0] = '\0';
  255. SECUREC_ERROR_INVALID_RANGE("strcpy_s");
  256. return ERANGE_AND_RESET;
  257. }
  258. return EOK;
  259. }
  260. /*
  261. * Handling errors
  262. */
  263. errno_t strcpy_error(char *strDest, size_t destMax, const char *strSrc)
  264. {
  265. if (destMax == 0 || destMax > SECUREC_STRING_MAX_LEN) {
  266. SECUREC_ERROR_INVALID_RANGE("strcpy_s");
  267. return ERANGE;
  268. } else if (strDest == NULL || strSrc == NULL) {
  269. SECUREC_ERROR_INVALID_PARAMTER("strcpy_s");
  270. if (strDest != NULL) {
  271. strDest[0] = '\0';
  272. return EINVAL_AND_RESET;
  273. }
  274. return EINVAL;
  275. }
  276. return CheckSrcRange(strDest, destMax, strSrc);
  277. }
  278. /*
  279. * Performance optimization. srcStrLen include '\0'
  280. */
  281. static void SecDoStrcpyOpt(char *strDest, const char *strSrc, size_t srcStrLen)
  282. {
  283. #if SECUREC_IN_KERNEL
  284. SecDoMemcpy(strDest, strSrc, srcStrLen);
  285. #else
  286. if (srcStrLen > SECUREC_STRCOPY_THRESHOLD_SIZE) {
  287. SecDoMemcpy(strDest, strSrc, srcStrLen);
  288. } else {
  289. SECUREC_SMALL_STR_COPY;
  290. }
  291. #endif
  292. }
  293. /*
  294. * <FUNCTION DESCRIPTION>
  295. * The strcpy_s function copies the string pointed to strSrc
  296. * (including the terminating null character) into the array pointed to by strDest
  297. * The destination string must be large enough to hold the source string,
  298. * including the terminating null character. strcpy_s will return EOVERLAP_AND_RESET
  299. * if the source and destination strings overlap.
  300. *
  301. * <INPUT PARAMETERS>
  302. * strDest Location of destination string buffer
  303. * destMax Size of the destination string buffer.
  304. * strSrc Null-terminated source string buffer.
  305. *
  306. * <OUTPUT PARAMETERS>
  307. * strDest is updated.
  308. *
  309. * <RETURN VALUE>
  310. * EOK Success
  311. * EINVAL strDest is NULL and destMax != 0 and destMax <= SECUREC_STRING_MAX_LEN
  312. * EINVAL_AND_RESET strDest != NULL and strSrc is NULL and destMax != 0 and destMax <= SECUREC_STRING_MAX_LEN
  313. * ERANGE destMax is 0 and destMax > SECUREC_STRING_MAX_LEN
  314. * ERANGE_AND_RESET strDest have not enough space and all other parameters are valid and not overlap
  315. * EOVERLAP_AND_RESET dest buffer and source buffer are overlapped and all parameters are valid
  316. *
  317. * If there is a runtime-constraint violation, strDest[0] will be set to the '\0' when strDest and destMax valid
  318. */
  319. errno_t strcpy_s(char *strDest, size_t destMax, const char *strSrc)
  320. {
  321. if ((destMax > 0 && destMax <= SECUREC_STRING_MAX_LEN && strDest != NULL && strSrc != NULL && strDest != strSrc)) {
  322. size_t srcStrLen = SecStrMinLen(strSrc, destMax) + 1; /* len include \0 */
  323. if (srcStrLen <= destMax) {
  324. /* use mem overlap check include \0 */
  325. if (SECUREC_MEMORY_NO_OVERLAP(strDest, strSrc, srcStrLen)) {
  326. /* performance optimization srcStrLen include '\0' */
  327. SecDoStrcpyOpt(strDest, strSrc, srcStrLen);
  328. return EOK;
  329. } else {
  330. strDest[0] = '\0';
  331. SECUREC_ERROR_BUFFER_OVERLAP("strcpy_s");
  332. return EOVERLAP_AND_RESET;
  333. }
  334. }
  335. }
  336. return strcpy_error(strDest, destMax, strSrc);
  337. }
  338. #if SECUREC_IN_KERNEL
  339. EXPORT_SYMBOL(strcpy_s);
  340. #endif