safec  2.1
Safe C Library - ISO TR24731 Bounds Checking Interface
mem_primitives_lib.c
Go to the documentation of this file.
1 /*------------------------------------------------------------------
2  * mem_primitives_lib.c - Unguarded Memory Copy Routines
3  *
4  * February 2005, Bo Berry
5  *
6  * Copyright (c) 2005-2009 Cisco Systems
7  * All rights reserved.
8  *
9  * Permission is hereby granted, free of charge, to any person
10  * obtaining a copy of this software and associated documentation
11  * files (the "Software"), to deal in the Software without
12  * restriction, including without limitation the rights to use,
13  * copy, modify, merge, publish, distribute, sublicense, and/or
14  * sell copies of the Software, and to permit persons to whom the
15  * Software is furnished to do so, subject to the following
16  * conditions:
17  *
18  * The above copyright notice and this permission notice shall be
19  * included in all copies or substantial portions of the Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28  * OTHER DEALINGS IN THE SOFTWARE.
29  *------------------------------------------------------------------
30  */
31 
32 #include "mem_primitives_lib.h"
33 
34 /*
35  * mem_primitives_lib.c provides unguarded memory routines
36  * that are used by the safe_mem_library. These routines
37  * may also be used by an application, but the application
38  * is responsible for all parameter validation and alignment.
39  */
40 
50 void
51 mem_prim_set (void *dest, uint32_t len, uint8_t value)
52 {
53  uint8_t *dp;
54  uint32_t count;
55  uint32_t lcount;
56 
57  uint32_t *lp;
58  uint32_t value32;
59 
60  count = len;
61 
62  dp = (uint8_t*) dest;
63 
64  value32 = value | (value << 8) | (value << 16) | (value << 24);
65 
66  /*
67  * First, do the few bytes to get uint32_t aligned.
68  */
69  for (; count && ( (uintptr_t)dp & (sizeof(uint32_t)-1) ); count--) {
70  *dp++ = value;
71  }
72 
73  /*
74  * Then do the uint32_ts, unrolled the loop for performance
75  */
76  lp = (uint32_t *)dp;
77  lcount = count >> 2;
78 
79  while (lcount != 0) {
80 
81  switch (lcount) {
82  /*
83  * Here we do blocks of 8. Once the remaining count
84  * drops below 8, take the fast track to finish up.
85  */
86  default:
87  *lp++ = value32; *lp++ = value32; *lp++ = value32; *lp++ = value32;
88  *lp++ = value32; *lp++ = value32; *lp++ = value32; *lp++ = value32;
89  *lp++ = value32; *lp++ = value32; *lp++ = value32; *lp++ = value32;
90  *lp++ = value32; *lp++ = value32; *lp++ = value32; *lp++ = value32;
91  lcount -= 16;
92  break;
93 
94  case 15: *lp++ = value32;
95  case 14: *lp++ = value32;
96  case 13: *lp++ = value32;
97  case 12: *lp++ = value32;
98  case 11: *lp++ = value32;
99  case 10: *lp++ = value32;
100  case 9: *lp++ = value32;
101  case 8: *lp++ = value32;
102 
103  case 7: *lp++ = value32;
104  case 6: *lp++ = value32;
105  case 5: *lp++ = value32;
106  case 4: *lp++ = value32;
107  case 3: *lp++ = value32;
108  case 2: *lp++ = value32;
109  case 1: *lp++ = value32;
110  lcount = 0;
111  break;
112  }
113  } /* end while */
114 
115 
116  dp = (uint8_t *)lp;
117 
118  /*
119  * compute the number of remaining bytes
120  */
121  count &= (sizeof(uint32_t)-1);
122 
123  /*
124  * remaining bytes
125  */
126  for (; count; dp++, count--) {
127  *dp = value;
128  }
129 
130  return;
131 }
132 
133 
144 void
145 mem_prim_set16 (uint16_t *dest, uint32_t len, uint16_t value)
146 {
147 
148  uint16_t *dp = dest;
149  while (len != 0) {
150 
151  switch (len) {
152  /*
153  * Here we do blocks of 8. Once the remaining count
154  * drops below 8, take the fast track to finish up.
155  */
156  default:
157  *dp++ = value; *dp++ = value; *dp++ = value; *dp++ = value;
158  *dp++ = value; *dp++ = value; *dp++ = value; *dp++ = value;
159  *dp++ = value; *dp++ = value; *dp++ = value; *dp++ = value;
160  *dp++ = value; *dp++ = value; *dp++ = value; *dp++ = value;
161  len -= 16;
162  break;
163 
164  case 15: *dp++ = value;
165  case 14: *dp++ = value;
166  case 13: *dp++ = value;
167  case 12: *dp++ = value;
168  case 11: *dp++ = value;
169  case 10: *dp++ = value;
170  case 9: *dp++ = value;
171  case 8: *dp++ = value;
172 
173  case 7: *dp++ = value;
174  case 6: *dp++ = value;
175  case 5: *dp++ = value;
176  case 4: *dp++ = value;
177  case 3: *dp++ = value;
178  case 2: *dp++ = value;
179  case 1: *dp++ = value;
180  len = 0;
181  break;
182  }
183  } /* end while */
184 
185  return;
186 }
187 
188 
200 void
201 mem_prim_set32 (uint32_t *dest, uint32_t len, uint32_t value)
202 {
203  uint32_t *dp = dest;
204  while (len != 0) {
205 
206  switch (len) {
207  /*
208  * Here we do blocks of 8. Once the remaining count
209  * drops below 8, take the fast track to finish up.
210  */
211  default:
212  *dp++ = value; *dp++ = value; *dp++ = value; *dp++ = value;
213  *dp++ = value; *dp++ = value; *dp++ = value; *dp++ = value;
214  *dp++ = value; *dp++ = value; *dp++ = value; *dp++ = value;
215  *dp++ = value; *dp++ = value; *dp++ = value; *dp++ = value;
216  len -= 16;
217  break;
218 
219  case 15: *dp++ = value;
220  case 14: *dp++ = value;
221  case 13: *dp++ = value;
222  case 12: *dp++ = value;
223  case 11: *dp++ = value;
224  case 10: *dp++ = value;
225  case 9: *dp++ = value;
226  case 8: *dp++ = value;
227 
228  case 7: *dp++ = value;
229  case 6: *dp++ = value;
230  case 5: *dp++ = value;
231  case 4: *dp++ = value;
232  case 3: *dp++ = value;
233  case 2: *dp++ = value;
234  case 1: *dp++ = value;
235  len = 0;
236  break;
237  }
238  } /* end while */
239 
240  return;
241 }
242 
243 
254 void
255 mem_prim_move (void *dest, const void *src, uint32_t len)
256 {
257 
258 #define wsize sizeof(uint32_t)
259 #define wmask (wsize - 1)
260 
261  uint8_t *dp = (uint8_t*) dest;
262  const uint8_t *sp = (uint8_t*) src;
263 
264  uint32_t tsp;
265 
266  /*
267  * Determine if we need to copy forward or backward (overlap)
268  */
269  if ((uintptr_t)dp < (uintptr_t)sp) {
270  /*
271  * Copy forward.
272  */
273 
274  /*
275  * get a working copy of src for bit operations
276  */
277  tsp = (uintptr_t)sp;
278 
279  /*
280  * Try to align both operands. This cannot be done
281  * unless the low bits match.
282  */
283  if ((tsp | (uintptr_t)dp) & wmask) {
284  /*
285  * determine how many bytes to copy to align operands
286  */
287  if ((tsp ^ (uintptr_t)dp) & wmask || len < wsize) {
288  tsp = len;
289 
290  } else {
291  tsp = wsize - (tsp & wmask);
292  }
293 
294  len -= tsp;
295 
296  /*
297  * make the alignment
298  */
299  do {
300  *dp++ = *sp++;
301  } while (--tsp);
302  }
303 
304  /*
305  * Now copy, then mop up any trailing bytes.
306  */
307  tsp = len / wsize;
308 
309  if (tsp > 0) {
310 
311  do {
312  *(uint32_t *)dp = *(uint32_t *)sp;
313 
314  sp += wsize;
315  dp += wsize;
316  } while (--tsp);
317  }
318 
319  /*
320  * copy over the remaining bytes and we're done
321  */
322  tsp = len & wmask;
323 
324  if (tsp > 0) {
325  do {
326  *dp++ = *sp++;
327  } while (--tsp);
328  }
329 
330  } else {
331  /*
332  * This section is used to copy backwards, to handle any
333  * overlap. The alignment requires (tps&wmask) bytes to
334  * align.
335  */
336 
337  /*
338  * go to end of the memory to copy
339  */
340  sp += len;
341  dp += len;
342 
343  /*
344  * get a working copy of src for bit operations
345  */
346  tsp = (uintptr_t)sp;
347 
348  /*
349  * Try to align both operands.
350  */
351  if ((tsp | (uintptr_t)dp) & wmask) {
352 
353  if ((tsp ^ (uintptr_t)dp) & wmask || len <= wsize) {
354  tsp = len;
355  } else {
356  tsp &= wmask;
357  }
358 
359  len -= tsp;
360 
361  /*
362  * make the alignment
363  */
364  do {
365  *--dp = *--sp;
366  } while (--tsp);
367  }
368 
369  /*
370  * Now copy in uint32_t units, then mop up any trailing bytes.
371  */
372  tsp = len / wsize;
373 
374  if (tsp > 0) {
375  do {
376  sp -= wsize;
377  dp -= wsize;
378 
379  *(uint32_t *)dp = *(uint32_t *)sp;
380  } while (--tsp);
381  }
382 
383  /*
384  * copy over the remaining bytes and we're done
385  */
386  tsp = len & wmask;
387  if (tsp > 0) {
388  tsp = len & wmask;
389  do {
390  *--dp = *--sp;
391  } while (--tsp);
392  }
393  }
394 
395  return;
396 }
397 
398 
410 void
411 mem_prim_move8 (uint8_t *dest, const uint8_t *src, uint32_t len)
412 {
413  uint8_t *dp = dest;
414  const uint8_t *sp = src;
415  /*
416  * Determine if we need to copy forward or backward (overlap)
417  */
418  if (dp < sp) {
419  /*
420  * Copy forward.
421  */
422 
423  while (len != 0) {
424 
425  switch (len) {
426  /*
427  * Here we do blocks of 8. Once the remaining count
428  * drops below 8, take the fast track to finish up.
429  */
430  default:
431  *dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp++;
432  *dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp++;
433  *dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp++;
434  *dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp++;
435  len -= 16;
436  break;
437 
438  case 15: *dp++ = *sp++;
439  case 14: *dp++ = *sp++;
440  case 13: *dp++ = *sp++;
441  case 12: *dp++ = *sp++;
442  case 11: *dp++ = *sp++;
443  case 10: *dp++ = *sp++;
444  case 9: *dp++ = *sp++;
445  case 8: *dp++ = *sp++;
446 
447  case 7: *dp++ = *sp++;
448  case 6: *dp++ = *sp++;
449  case 5: *dp++ = *sp++;
450  case 4: *dp++ = *sp++;
451  case 3: *dp++ = *sp++;
452  case 2: *dp++ = *sp++;
453  case 1: *dp++ = *sp++;
454  len = 0;
455  break;
456  }
457  } /* end while */
458 
459  } else {
460  /*
461  * This section is used to copy backwards, to handle any
462  * overlap. The alignment requires (tps&wmask) bytes to
463  * align.
464  */
465 
466 
467  /*
468  * go to end of the memory to copy
469  */
470  sp += len;
471  dp += len;
472 
473  while (len != 0) {
474 
475  switch (len) {
476  /*
477  * Here we do blocks of 8. Once the remaining count
478  * drops below 8, take the fast track to finish up.
479  */
480  default:
481  *--dp = *--sp; *--dp = *--sp; *--dp = *--sp; *--dp = *--sp;
482  *--dp = *--sp; *--dp = *--sp; *--dp = *--sp; *--dp = *--sp;
483  *--dp = *--sp; *--dp = *--sp; *--dp = *--sp; *--dp = *--sp;
484  *--dp = *--sp; *--dp = *--sp; *--dp = *--sp; *--dp = *--sp;
485  len -= 16;
486  break;
487 
488  case 15: *--dp = *--sp;
489  case 14: *--dp = *--sp;
490  case 13: *--dp = *--sp;
491  case 12: *--dp = *--sp;
492  case 11: *--dp = *--sp;
493  case 10: *--dp = *--sp;
494  case 9: *--dp = *--sp;
495  case 8: *--dp = *--sp;
496 
497  case 7: *--dp = *--sp;
498  case 6: *--dp = *--sp;
499  case 5: *--dp = *--sp;
500  case 4: *--dp = *--sp;
501  case 3: *--dp = *--sp;
502  case 2: *--dp = *--sp;
503  case 1: *--dp = *--sp;
504  len = 0;
505  break;
506  }
507  } /* end while */
508  }
509 
510  return;
511 }
512 
513 
524 void
525 mem_prim_move16 (uint16_t *dest, const uint16_t *src, uint32_t len)
526 {
527  uint16_t *dp = dest;
528  const uint16_t *sp = src;
529  /*
530  * Determine if we need to copy forward or backward (overlap)
531  */
532  if (dp < sp) {
533  /*
534  * Copy forward.
535  */
536 
537  while (len != 0) {
538 
539  switch (len) {
540  /*
541  * Here we do blocks of 8. Once the remaining count
542  * drops below 8, take the fast track to finish up.
543  */
544  default:
545  *dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp++;
546  *dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp++;
547  *dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp++;
548  *dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp++;
549  len -= 16;
550  break;
551 
552  case 15: *dp++ = *sp++;
553  case 14: *dp++ = *sp++;
554  case 13: *dp++ = *sp++;
555  case 12: *dp++ = *sp++;
556  case 11: *dp++ = *sp++;
557  case 10: *dp++ = *sp++;
558  case 9: *dp++ = *sp++;
559  case 8: *dp++ = *sp++;
560 
561  case 7: *dp++ = *sp++;
562  case 6: *dp++ = *sp++;
563  case 5: *dp++ = *sp++;
564  case 4: *dp++ = *sp++;
565  case 3: *dp++ = *sp++;
566  case 2: *dp++ = *sp++;
567  case 1: *dp++ = *sp++;
568  len = 0;
569  break;
570  }
571  } /* end while */
572 
573  } else {
574  /*
575  * This section is used to copy backwards, to handle any
576  * overlap. The alignment requires (tps&wmask) bytes to
577  * align.
578  */
579 
580  /*
581  * go to end of the memory to copy
582  */
583  sp += len;
584  dp += len;
585 
586  while (len != 0) {
587 
588  switch (len) {
589  /*
590  * Here we do blocks of 8. Once the remaining count
591  * drops below 8, take the fast track to finish up.
592  */
593  default:
594  *--dp = *--sp; *--dp = *--sp; *--dp = *--sp; *--dp = *--sp;
595  *--dp = *--sp; *--dp = *--sp; *--dp = *--sp; *--dp = *--sp;
596  *--dp = *--sp; *--dp = *--sp; *--dp = *--sp; *--dp = *--sp;
597  *--dp = *--sp; *--dp = *--sp; *--dp = *--sp; *--dp = *--sp;
598  len -= 16;
599  break;
600 
601  case 15: *--dp = *--sp;
602  case 14: *--dp = *--sp;
603  case 13: *--dp = *--sp;
604  case 12: *--dp = *--sp;
605  case 11: *--dp = *--sp;
606  case 10: *--dp = *--sp;
607  case 9: *--dp = *--sp;
608  case 8: *--dp = *--sp;
609 
610  case 7: *--dp = *--sp;
611  case 6: *--dp = *--sp;
612  case 5: *--dp = *--sp;
613  case 4: *--dp = *--sp;
614  case 3: *--dp = *--sp;
615  case 2: *--dp = *--sp;
616  case 1: *--dp = *--sp;
617  len = 0;
618  break;
619  }
620  } /* end while */
621  }
622 
623  return;
624 }
625 
626 
637 void
638 mem_prim_move32 (uint32_t *dest, const uint32_t *src, uint32_t len)
639 {
640  uint32_t *dp = dest;
641  const uint32_t *sp = src;
642  /*
643  * Determine if we need to copy forward or backward (overlap)
644  */
645  if (dp < sp) {
646  /*
647  * Copy forward.
648  */
649 
650  while (len != 0) {
651 
652  switch (len) {
653  /*
654  * Here we do blocks of 8. Once the remaining count
655  * drops below 8, take the fast track to finish up.
656  */
657  default:
658  *dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp++;
659  *dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp++;
660  *dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp++;
661  *dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp++;
662  len -= 16;
663  break;
664 
665  case 15: *dp++ = *sp++;
666  case 14: *dp++ = *sp++;
667  case 13: *dp++ = *sp++;
668  case 12: *dp++ = *sp++;
669  case 11: *dp++ = *sp++;
670  case 10: *dp++ = *sp++;
671  case 9: *dp++ = *sp++;
672  case 8: *dp++ = *sp++;
673 
674  case 7: *dp++ = *sp++;
675  case 6: *dp++ = *sp++;
676  case 5: *dp++ = *sp++;
677  case 4: *dp++ = *sp++;
678  case 3: *dp++ = *sp++;
679  case 2: *dp++ = *sp++;
680  case 1: *dp++ = *sp++;
681  len = 0;
682  break;
683  }
684  } /* end while */
685 
686  } else {
687  /*
688  * This section is used to copy backwards, to handle any
689  * overlap.
690  */
691 
692  /*
693  * go to end of the memory to copy
694  */
695  sp += len;
696  dp += len;
697 
698  while (len != 0) {
699 
700  switch (len) {
701  /*
702  * Here we do blocks of 8. Once the remaining count
703  * drops below 8, take the fast track to finish up.
704  */
705  default:
706  *--dp = *--sp; *--dp = *--sp; *--dp = *--sp; *--dp = *--sp;
707  *--dp = *--sp; *--dp = *--sp; *--dp = *--sp; *--dp = *--sp;
708  *--dp = *--sp; *--dp = *--sp; *--dp = *--sp; *--dp = *--sp;
709  *--dp = *--sp; *--dp = *--sp; *--dp = *--sp; *--dp = *--sp;
710  len -= 16;
711  break;
712 
713  case 15: *--dp = *--sp;
714  case 14: *--dp = *--sp;
715  case 13: *--dp = *--sp;
716  case 12: *--dp = *--sp;
717  case 11: *--dp = *--sp;
718  case 10: *--dp = *--sp;
719  case 9: *--dp = *--sp;
720  case 8: *--dp = *--sp;
721 
722  case 7: *--dp = *--sp;
723  case 6: *--dp = *--sp;
724  case 5: *--dp = *--sp;
725  case 4: *--dp = *--sp;
726  case 3: *--dp = *--sp;
727  case 2: *--dp = *--sp;
728  case 1: *--dp = *--sp;
729  len = 0;
730  break;
731  }
732  } /* end while */
733  }
734 
735  return;
736 }
void mem_prim_set32(uint32_t *dest, uint32_t len, uint32_t value)
Sets len uint32_t&#39;s starting at dest to the specified value.
#define wsize
void mem_prim_move8(uint8_t *dest, const uint8_t *src, uint32_t len)
Moves at most len of uint8_t&#39;s from src to dest.
void mem_prim_move32(uint32_t *dest, const uint32_t *src, uint32_t len)
Moves at most len of uint32_t&#39;s from src to dest.
#define wmask
void mem_prim_set(void *dest, uint32_t len, uint8_t value)
Sets len bytes starting at dest to the specified value.
void mem_prim_set16(uint16_t *dest, uint32_t len, uint16_t value)
Sets len uint16_t&#39;s starting at dest to the specified value.
void mem_prim_move(void *dest, const void *src, uint32_t len)
Moves at most len of bytes from src to dest.
void mem_prim_move16(uint16_t *dest, const uint16_t *src, uint32_t len)
Moves at most len uint16_t&#39;s from src to dest.