Merge branch 'master' of ssh://sourceware.org/git/glibc
[platform/upstream/glibc.git] / debug / memset_chk.c
1 /* Copyright (C) 1991, 1997, 2003, 2004, 2005 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, write to the Free
16    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17    02111-1307 USA.  */
18
19 #include <string.h>
20 #include <memcopy.h>
21
22 void *
23 __memset_chk (dstpp, c, len, dstlen)
24      void *dstpp;
25      int c;
26      size_t len;
27      size_t dstlen;
28 {
29   if (__builtin_expect (dstlen < len, 0))
30     __chk_fail ();
31
32   long int dstp = (long int) dstpp;
33
34   if (len >= 8)
35     {
36       size_t xlen;
37       op_t cccc;
38
39       cccc = (unsigned char) c;
40       cccc |= cccc << 8;
41       cccc |= cccc << 16;
42       if (OPSIZ > 4)
43         /* Do the shift in two steps to avoid warning if long has 32 bits.  */
44         cccc |= (cccc << 16) << 16;
45
46       /* There are at least some bytes to set.
47          No need to test for LEN == 0 in this alignment loop.  */
48       while (dstp % OPSIZ != 0)
49         {
50           ((byte *) dstp)[0] = c;
51           dstp += 1;
52           len -= 1;
53         }
54
55       /* Write 8 `op_t' per iteration until less than 8 `op_t' remain.  */
56       xlen = len / (OPSIZ * 8);
57       while (xlen > 0)
58         {
59           ((op_t *) dstp)[0] = cccc;
60           ((op_t *) dstp)[1] = cccc;
61           ((op_t *) dstp)[2] = cccc;
62           ((op_t *) dstp)[3] = cccc;
63           ((op_t *) dstp)[4] = cccc;
64           ((op_t *) dstp)[5] = cccc;
65           ((op_t *) dstp)[6] = cccc;
66           ((op_t *) dstp)[7] = cccc;
67           dstp += 8 * OPSIZ;
68           xlen -= 1;
69         }
70       len %= OPSIZ * 8;
71
72       /* Write 1 `op_t' per iteration until less than OPSIZ bytes remain.  */
73       xlen = len / OPSIZ;
74       while (xlen > 0)
75         {
76           ((op_t *) dstp)[0] = cccc;
77           dstp += OPSIZ;
78           xlen -= 1;
79         }
80       len %= OPSIZ;
81     }
82
83   /* Write the last few bytes.  */
84   while (len > 0)
85     {
86       ((byte *) dstp)[0] = c;
87       dstp += 1;
88       len -= 1;
89     }
90
91   return dstpp;
92 }