Blame view

include/linux/string.h 16.4 KB
b24413180   Greg Kroah-Hartman   License cleanup: ...
1
  /* SPDX-License-Identifier: GPL-2.0 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
  #ifndef _LINUX_STRING_H_
  #define _LINUX_STRING_H_
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4
5
6
7
  
  #include <linux/compiler.h>	/* for inline */
  #include <linux/types.h>	/* for size_t */
  #include <linux/stddef.h>	/* for NULL */
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
8
  #include <stdarg.h>
607ca46e9   David Howells   UAPI: (Scripted) ...
9
  #include <uapi/linux/string.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
10

96840aa00   Davi Arnaut   [PATCH] strndup_u...
11
  extern char *strndup_user(const char __user *, long);
610a77e04   Li Zefan   memdup_user(): in...
12
  extern void *memdup_user(const void __user *, size_t);
50fd2f298   Al Viro   new primitive: vm...
13
  extern void *vmemdup_user(const void __user *, size_t);
e9d408e10   Al Viro   new helper: memdu...
14
  extern void *memdup_user_nul(const void __user *, size_t);
96840aa00   Davi Arnaut   [PATCH] strndup_u...
15

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  /*
   * Include machine specific inline routines
   */
  #include <asm/string.h>
  
  #ifndef __HAVE_ARCH_STRCPY
  extern char * strcpy(char *,const char *);
  #endif
  #ifndef __HAVE_ARCH_STRNCPY
  extern char * strncpy(char *,const char *, __kernel_size_t);
  #endif
  #ifndef __HAVE_ARCH_STRLCPY
  size_t strlcpy(char *, const char *, size_t);
  #endif
30035e457   Chris Metcalf   string: provide s...
30
  #ifndef __HAVE_ARCH_STRSCPY
08a77676f   Tejun Heo   string: drop __mu...
31
  ssize_t strscpy(char *, const char *, size_t);
30035e457   Chris Metcalf   string: provide s...
32
  #endif
458a3bf82   Tobin C. Harding   lib/string: Add s...
33
34
35
  
  /* Wraps calls to strscpy()/memset(), no arch specific code required */
  ssize_t strscpy_pad(char *dest, const char *src, size_t count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
  #ifndef __HAVE_ARCH_STRCAT
  extern char * strcat(char *, const char *);
  #endif
  #ifndef __HAVE_ARCH_STRNCAT
  extern char * strncat(char *, const char *, __kernel_size_t);
  #endif
  #ifndef __HAVE_ARCH_STRLCAT
  extern size_t strlcat(char *, const char *, __kernel_size_t);
  #endif
  #ifndef __HAVE_ARCH_STRCMP
  extern int strcmp(const char *,const char *);
  #endif
  #ifndef __HAVE_ARCH_STRNCMP
  extern int strncmp(const char *,const char *,__kernel_size_t);
  #endif
ded220bd8   David S. Miller   [STRING]: Move st...
51
52
53
54
55
56
  #ifndef __HAVE_ARCH_STRCASECMP
  extern int strcasecmp(const char *s1, const char *s2);
  #endif
  #ifndef __HAVE_ARCH_STRNCASECMP
  extern int strncasecmp(const char *s1, const char *s2, size_t n);
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
57
58
59
  #ifndef __HAVE_ARCH_STRCHR
  extern char * strchr(const char *,int);
  #endif
11d200e95   Grant Likely   lib: add glibc st...
60
61
62
  #ifndef __HAVE_ARCH_STRCHRNUL
  extern char * strchrnul(const char *,int);
  #endif
0bee0cece   Yury Norov   lib/string: add s...
63
  extern char * strnchrnul(const char *, size_t, int);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
65
66
67
68
69
  #ifndef __HAVE_ARCH_STRNCHR
  extern char * strnchr(const char *, size_t, int);
  #endif
  #ifndef __HAVE_ARCH_STRRCHR
  extern char * strrchr(const char *,int);
  #endif
f653398c8   AndrĂ© Goddard Rosa   string: factorize...
70
  extern char * __must_check skip_spaces(const char *);
ca54cb8c9   KOSAKI Motohiro   Subject: Re: [PAT...
71
72
73
74
75
76
77
  
  extern char *strim(char *);
  
  static inline __must_check char *strstrip(char *str)
  {
  	return strim(str);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
  #ifndef __HAVE_ARCH_STRSTR
d5f1fb533   Li Zefan   lib: Introduce st...
79
80
81
82
  extern char * strstr(const char *, const char *);
  #endif
  #ifndef __HAVE_ARCH_STRNSTR
  extern char * strnstr(const char *, const char *, size_t);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
83
84
85
86
87
88
89
  #endif
  #ifndef __HAVE_ARCH_STRLEN
  extern __kernel_size_t strlen(const char *);
  #endif
  #ifndef __HAVE_ARCH_STRNLEN
  extern __kernel_size_t strnlen(const char *,__kernel_size_t);
  #endif
8833d328c   Kyle McMartin   [PATCH] Clean up ...
90
91
92
93
94
95
96
97
98
99
100
101
  #ifndef __HAVE_ARCH_STRPBRK
  extern char * strpbrk(const char *,const char *);
  #endif
  #ifndef __HAVE_ARCH_STRSEP
  extern char * strsep(char **,const char *);
  #endif
  #ifndef __HAVE_ARCH_STRSPN
  extern __kernel_size_t strspn(const char *,const char *);
  #endif
  #ifndef __HAVE_ARCH_STRCSPN
  extern __kernel_size_t strcspn(const char *,const char *);
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
102
103
104
105
  
  #ifndef __HAVE_ARCH_MEMSET
  extern void * memset(void *,int,__kernel_size_t);
  #endif
3b3c4babd   Matthew Wilcox   lib/string.c: add...
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
  
  #ifndef __HAVE_ARCH_MEMSET16
  extern void *memset16(uint16_t *, uint16_t, __kernel_size_t);
  #endif
  
  #ifndef __HAVE_ARCH_MEMSET32
  extern void *memset32(uint32_t *, uint32_t, __kernel_size_t);
  #endif
  
  #ifndef __HAVE_ARCH_MEMSET64
  extern void *memset64(uint64_t *, uint64_t, __kernel_size_t);
  #endif
  
  static inline void *memset_l(unsigned long *p, unsigned long v,
  		__kernel_size_t n)
  {
  	if (BITS_PER_LONG == 32)
  		return memset32((uint32_t *)p, v, n);
  	else
  		return memset64((uint64_t *)p, v, n);
  }
  
  static inline void *memset_p(void **p, void *v, __kernel_size_t n)
  {
  	if (BITS_PER_LONG == 32)
  		return memset32((uint32_t *)p, (uintptr_t)v, n);
  	else
  		return memset64((uint64_t *)p, (uintptr_t)v, n);
  }
ce76d938d   Alexander Shishkin   lib: Add memcat_p...
135
136
137
138
139
140
  extern void **__memcat_p(void **a, void **b);
  #define memcat_p(a, b) ({					\
  	BUILD_BUG_ON_MSG(!__same_type(*(a), *(b)),		\
  			 "type mismatch in memcat_p()");	\
  	(typeof(*a) *)__memcat_p((void **)(a), (void **)(b));	\
  })
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
141
142
143
144
145
146
147
148
149
150
151
152
  #ifndef __HAVE_ARCH_MEMCPY
  extern void * memcpy(void *,const void *,__kernel_size_t);
  #endif
  #ifndef __HAVE_ARCH_MEMMOVE
  extern void * memmove(void *,const void *,__kernel_size_t);
  #endif
  #ifndef __HAVE_ARCH_MEMSCAN
  extern void * memscan(void *,int,__kernel_size_t);
  #endif
  #ifndef __HAVE_ARCH_MEMCMP
  extern int memcmp(const void *,const void *,__kernel_size_t);
  #endif
5f074f3e1   Nick Desaulniers   lib/string.c: imp...
153
154
155
  #ifndef __HAVE_ARCH_BCMP
  extern int bcmp(const void *,const void *,__kernel_size_t);
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
156
157
158
  #ifndef __HAVE_ARCH_MEMCHR
  extern void * memchr(const void *,int,__kernel_size_t);
  #endif
0aed55af8   Dan Williams   x86, uaccess: int...
159
160
161
162
163
164
  #ifndef __HAVE_ARCH_MEMCPY_FLUSHCACHE
  static inline void memcpy_flushcache(void *dst, const void *src, size_t cnt)
  {
  	memcpy(dst, src, cnt);
  }
  #endif
ec6347bb4   Dan Williams   x86, powerpc: Ren...
165

798248206   Akinobu Mita   lib/string.c: int...
166
  void *memchr_inv(const void *s, int c, size_t n);
94df29040   Rasmus Villemoes   lib/string.c: int...
167
  char *strreplace(char *s, char old, char new);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
168

a4bb1e43e   Andrzej Hajda   mm/util: add kstr...
169
  extern void kfree_const(const void *x);
48a270554   Rasmus Villemoes   include/linux: ap...
170
  extern char *kstrdup(const char *s, gfp_t gfp) __malloc;
a4bb1e43e   Andrzej Hajda   mm/util: add kstr...
171
  extern const char *kstrdup_const(const char *s, gfp_t gfp);
1e66df3ee   Jeremy Fitzhardinge   add kstrndup
172
  extern char *kstrndup(const char *s, size_t len, gfp_t gfp);
1a2f67b45   Alexey Dobriyan   [PATCH] kmemdup: ...
173
  extern void *kmemdup(const void *src, size_t len, gfp_t gfp);
f35157417   David Howells   Provide a functio...
174
  extern char *kmemdup_nul(const char *s, size_t len, gfp_t gfp);
543537bd9   Paulo Marques   [PATCH] create a ...
175

d84d1cc76   Jeremy Fitzhardinge   add argv_split()
176
177
  extern char **argv_split(gfp_t gfp, const char *str, int *argcp);
  extern void argv_free(char **argv);
34990cf70   David Brownell   Add a new sysfs_s...
178
  extern bool sysfs_streq(const char *s1, const char *s2);
ef9515990   Kees Cook   lib: move strtobo...
179
180
181
182
183
  extern int kstrtobool(const char *s, bool *res);
  static inline int strtobool(const char *s, bool *res)
  {
  	return kstrtobool(s, res);
  }
34990cf70   David Brownell   Add a new sysfs_s...
184

56b060814   Andy Shevchenko   lib/string: intro...
185
  int match_string(const char * const *array, size_t n, const char *string);
e1fe7b6a7   Heikki Krogerus   lib/string: add s...
186
187
188
189
190
191
192
193
194
195
  int __sysfs_match_string(const char * const *array, size_t n, const char *s);
  
  /**
   * sysfs_match_string - matches given string in an array
   * @_a: array of strings
   * @_s: string to match with
   *
   * Helper for __sysfs_match_string(). Calculates the size of @a automatically.
   */
  #define sysfs_match_string(_a, _s) __sysfs_match_string(_a, ARRAY_SIZE(_a), _s)
56b060814   Andy Shevchenko   lib/string: intro...
196

4370aa4aa   Lai Jiangshan   vsprintf: add bin...
197
198
199
200
201
  #ifdef CONFIG_BINARY_PRINTF
  int vbin_printf(u32 *bin_buf, size_t size, const char *fmt, va_list args);
  int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf);
  int bprintf(u32 *bin_buf, size_t size, const char *fmt, ...) __printf(3, 4);
  #endif
e108526e7   Akinobu Mita   move memory_read_...
202
  extern ssize_t memory_read_from_buffer(void *to, size_t count, loff_t *ppos,
d4c5efdb9   Daniel Borkmann   random: add and u...
203
  				       const void *from, size_t available);
e108526e7   Akinobu Mita   move memory_read_...
204

e4dcad204   Joel Fernandes (Google)   rss_stat: add sup...
205
  int ptr_to_hashval(const void *ptr, unsigned long *hashval_out);
66f92cf9d   Rusty Russell   strstarts: helper...
206
207
208
209
210
211
212
213
214
  /**
   * strstarts - does @str start with @prefix?
   * @str: string to examine
   * @prefix: prefix to look for.
   */
  static inline bool strstarts(const char *str, const char *prefix)
  {
  	return strncmp(str, prefix, strlen(prefix)) == 0;
  }
639b9e34f   Akinobu Mita   string: introduce...
215

d4c5efdb9   Daniel Borkmann   random: add and u...
216
  size_t memweight(const void *ptr, size_t bytes);
bec500777   Arvind Sankar   lib/string: Make ...
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
  
  /**
   * memzero_explicit - Fill a region of memory (e.g. sensitive
   *		      keying data) with 0s.
   * @s: Pointer to the start of the area.
   * @count: The size of the area.
   *
   * Note: usually using memset() is just fine (!), but in cases
   * where clearing out _local_ data at the end of a scope is
   * necessary, memzero_explicit() should be used instead in
   * order to prevent the compiler from optimising away zeroing.
   *
   * memzero_explicit() doesn't need an arch-specific version as
   * it just invokes the one of memset() implicitly.
   */
  static inline void memzero_explicit(void *s, size_t count)
  {
  	memset(s, 0, count);
  	barrier_data(s);
  }
639b9e34f   Akinobu Mita   string: introduce...
237

b18888ab2   Andy Shevchenko   string: introduce...
238
239
240
241
242
243
244
245
246
247
  /**
   * kbasename - return the last part of a pathname.
   *
   * @path: path to extract the filename from.
   */
  static inline const char *kbasename(const char *path)
  {
  	const char *tail = strrchr(path, '/');
  	return tail ? tail + 1 : path;
  }
6974f0c45   Daniel Micay   include/linux/str...
248
249
250
251
252
253
  #define __FORTIFY_INLINE extern __always_inline __attribute__((gnu_inline))
  #define __RENAME(x) __asm__(#x)
  
  void fortify_panic(const char *name) __noreturn __cold;
  void __read_overflow(void) __compiletime_error("detected read beyond size of object passed as 1st parameter");
  void __read_overflow2(void) __compiletime_error("detected read beyond size of object passed as 2nd parameter");
01f33c336   Martin Wilck   string.h: add mem...
254
  void __read_overflow3(void) __compiletime_error("detected read beyond size of object passed as 3rd parameter");
6974f0c45   Daniel Micay   include/linux/str...
255
256
257
  void __write_overflow(void) __compiletime_error("detected write beyond size of object passed as 1st parameter");
  
  #if !defined(__NO_FORTIFY) && defined(__OPTIMIZE__) && defined(CONFIG_FORTIFY_SOURCE)
47227d27e   Daniel Axtens   string.h: fix inc...
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
  
  #ifdef CONFIG_KASAN
  extern void *__underlying_memchr(const void *p, int c, __kernel_size_t size) __RENAME(memchr);
  extern int __underlying_memcmp(const void *p, const void *q, __kernel_size_t size) __RENAME(memcmp);
  extern void *__underlying_memcpy(void *p, const void *q, __kernel_size_t size) __RENAME(memcpy);
  extern void *__underlying_memmove(void *p, const void *q, __kernel_size_t size) __RENAME(memmove);
  extern void *__underlying_memset(void *p, int c, __kernel_size_t size) __RENAME(memset);
  extern char *__underlying_strcat(char *p, const char *q) __RENAME(strcat);
  extern char *__underlying_strcpy(char *p, const char *q) __RENAME(strcpy);
  extern __kernel_size_t __underlying_strlen(const char *p) __RENAME(strlen);
  extern char *__underlying_strncat(char *p, const char *q, __kernel_size_t count) __RENAME(strncat);
  extern char *__underlying_strncpy(char *p, const char *q, __kernel_size_t size) __RENAME(strncpy);
  #else
  #define __underlying_memchr	__builtin_memchr
  #define __underlying_memcmp	__builtin_memcmp
  #define __underlying_memcpy	__builtin_memcpy
  #define __underlying_memmove	__builtin_memmove
  #define __underlying_memset	__builtin_memset
  #define __underlying_strcat	__builtin_strcat
  #define __underlying_strcpy	__builtin_strcpy
  #define __underlying_strlen	__builtin_strlen
  #define __underlying_strncat	__builtin_strncat
  #define __underlying_strncpy	__builtin_strncpy
  #endif
6974f0c45   Daniel Micay   include/linux/str...
282
283
284
285
286
287
288
  __FORTIFY_INLINE char *strncpy(char *p, const char *q, __kernel_size_t size)
  {
  	size_t p_size = __builtin_object_size(p, 0);
  	if (__builtin_constant_p(size) && p_size < size)
  		__write_overflow();
  	if (p_size < size)
  		fortify_panic(__func__);
47227d27e   Daniel Axtens   string.h: fix inc...
289
  	return __underlying_strncpy(p, q, size);
6974f0c45   Daniel Micay   include/linux/str...
290
291
292
293
294
295
  }
  
  __FORTIFY_INLINE char *strcat(char *p, const char *q)
  {
  	size_t p_size = __builtin_object_size(p, 0);
  	if (p_size == (size_t)-1)
47227d27e   Daniel Axtens   string.h: fix inc...
296
  		return __underlying_strcat(p, q);
6974f0c45   Daniel Micay   include/linux/str...
297
298
299
300
301
302
303
304
305
  	if (strlcat(p, q, p_size) >= p_size)
  		fortify_panic(__func__);
  	return p;
  }
  
  __FORTIFY_INLINE __kernel_size_t strlen(const char *p)
  {
  	__kernel_size_t ret;
  	size_t p_size = __builtin_object_size(p, 0);
146734b09   Arnd Bergmann   string.h: workaro...
306
307
308
309
  
  	/* Work around gcc excess stack consumption issue */
  	if (p_size == (size_t)-1 ||
  	    (__builtin_constant_p(p[p_size - 1]) && p[p_size - 1] == '\0'))
47227d27e   Daniel Axtens   string.h: fix inc...
310
  		return __underlying_strlen(p);
6974f0c45   Daniel Micay   include/linux/str...
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
  	ret = strnlen(p, p_size);
  	if (p_size <= ret)
  		fortify_panic(__func__);
  	return ret;
  }
  
  extern __kernel_size_t __real_strnlen(const char *, __kernel_size_t) __RENAME(strnlen);
  __FORTIFY_INLINE __kernel_size_t strnlen(const char *p, __kernel_size_t maxlen)
  {
  	size_t p_size = __builtin_object_size(p, 0);
  	__kernel_size_t ret = __real_strnlen(p, maxlen < p_size ? maxlen : p_size);
  	if (p_size <= ret && maxlen != ret)
  		fortify_panic(__func__);
  	return ret;
  }
  
  /* defined after fortified strlen to reuse it */
  extern size_t __real_strlcpy(char *, const char *, size_t) __RENAME(strlcpy);
  __FORTIFY_INLINE size_t strlcpy(char *p, const char *q, size_t size)
  {
  	size_t ret;
  	size_t p_size = __builtin_object_size(p, 0);
  	size_t q_size = __builtin_object_size(q, 0);
  	if (p_size == (size_t)-1 && q_size == (size_t)-1)
  		return __real_strlcpy(p, q, size);
  	ret = strlen(q);
  	if (size) {
  		size_t len = (ret >= size) ? size - 1 : ret;
  		if (__builtin_constant_p(len) && len >= p_size)
  			__write_overflow();
  		if (len >= p_size)
  			fortify_panic(__func__);
47227d27e   Daniel Axtens   string.h: fix inc...
343
  		__underlying_memcpy(p, q, len);
6974f0c45   Daniel Micay   include/linux/str...
344
345
346
347
348
349
350
351
352
353
354
355
  		p[len] = '\0';
  	}
  	return ret;
  }
  
  /* defined after fortified strlen and strnlen to reuse them */
  __FORTIFY_INLINE char *strncat(char *p, const char *q, __kernel_size_t count)
  {
  	size_t p_len, copy_len;
  	size_t p_size = __builtin_object_size(p, 0);
  	size_t q_size = __builtin_object_size(q, 0);
  	if (p_size == (size_t)-1 && q_size == (size_t)-1)
47227d27e   Daniel Axtens   string.h: fix inc...
356
  		return __underlying_strncat(p, q, count);
6974f0c45   Daniel Micay   include/linux/str...
357
358
359
360
  	p_len = strlen(p);
  	copy_len = strnlen(q, count);
  	if (p_size < p_len + copy_len + 1)
  		fortify_panic(__func__);
47227d27e   Daniel Axtens   string.h: fix inc...
361
  	__underlying_memcpy(p + p_len, q, copy_len);
6974f0c45   Daniel Micay   include/linux/str...
362
363
364
365
366
367
368
369
370
371
372
  	p[p_len + copy_len] = '\0';
  	return p;
  }
  
  __FORTIFY_INLINE void *memset(void *p, int c, __kernel_size_t size)
  {
  	size_t p_size = __builtin_object_size(p, 0);
  	if (__builtin_constant_p(size) && p_size < size)
  		__write_overflow();
  	if (p_size < size)
  		fortify_panic(__func__);
47227d27e   Daniel Axtens   string.h: fix inc...
373
  	return __underlying_memset(p, c, size);
6974f0c45   Daniel Micay   include/linux/str...
374
375
376
377
378
379
380
381
382
383
384
385
386
387
  }
  
  __FORTIFY_INLINE void *memcpy(void *p, const void *q, __kernel_size_t size)
  {
  	size_t p_size = __builtin_object_size(p, 0);
  	size_t q_size = __builtin_object_size(q, 0);
  	if (__builtin_constant_p(size)) {
  		if (p_size < size)
  			__write_overflow();
  		if (q_size < size)
  			__read_overflow2();
  	}
  	if (p_size < size || q_size < size)
  		fortify_panic(__func__);
47227d27e   Daniel Axtens   string.h: fix inc...
388
  	return __underlying_memcpy(p, q, size);
6974f0c45   Daniel Micay   include/linux/str...
389
390
391
392
393
394
395
396
397
398
399
400
401
402
  }
  
  __FORTIFY_INLINE void *memmove(void *p, const void *q, __kernel_size_t size)
  {
  	size_t p_size = __builtin_object_size(p, 0);
  	size_t q_size = __builtin_object_size(q, 0);
  	if (__builtin_constant_p(size)) {
  		if (p_size < size)
  			__write_overflow();
  		if (q_size < size)
  			__read_overflow2();
  	}
  	if (p_size < size || q_size < size)
  		fortify_panic(__func__);
47227d27e   Daniel Axtens   string.h: fix inc...
403
  	return __underlying_memmove(p, q, size);
6974f0c45   Daniel Micay   include/linux/str...
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
  }
  
  extern void *__real_memscan(void *, int, __kernel_size_t) __RENAME(memscan);
  __FORTIFY_INLINE void *memscan(void *p, int c, __kernel_size_t size)
  {
  	size_t p_size = __builtin_object_size(p, 0);
  	if (__builtin_constant_p(size) && p_size < size)
  		__read_overflow();
  	if (p_size < size)
  		fortify_panic(__func__);
  	return __real_memscan(p, c, size);
  }
  
  __FORTIFY_INLINE int memcmp(const void *p, const void *q, __kernel_size_t size)
  {
  	size_t p_size = __builtin_object_size(p, 0);
  	size_t q_size = __builtin_object_size(q, 0);
  	if (__builtin_constant_p(size)) {
  		if (p_size < size)
  			__read_overflow();
  		if (q_size < size)
  			__read_overflow2();
  	}
  	if (p_size < size || q_size < size)
  		fortify_panic(__func__);
47227d27e   Daniel Axtens   string.h: fix inc...
429
  	return __underlying_memcmp(p, q, size);
6974f0c45   Daniel Micay   include/linux/str...
430
431
432
433
434
435
436
437
438
  }
  
  __FORTIFY_INLINE void *memchr(const void *p, int c, __kernel_size_t size)
  {
  	size_t p_size = __builtin_object_size(p, 0);
  	if (__builtin_constant_p(size) && p_size < size)
  		__read_overflow();
  	if (p_size < size)
  		fortify_panic(__func__);
47227d27e   Daniel Axtens   string.h: fix inc...
439
  	return __underlying_memchr(p, c, size);
6974f0c45   Daniel Micay   include/linux/str...
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
  }
  
  void *__real_memchr_inv(const void *s, int c, size_t n) __RENAME(memchr_inv);
  __FORTIFY_INLINE void *memchr_inv(const void *p, int c, size_t size)
  {
  	size_t p_size = __builtin_object_size(p, 0);
  	if (__builtin_constant_p(size) && p_size < size)
  		__read_overflow();
  	if (p_size < size)
  		fortify_panic(__func__);
  	return __real_memchr_inv(p, c, size);
  }
  
  extern void *__real_kmemdup(const void *src, size_t len, gfp_t gfp) __RENAME(kmemdup);
  __FORTIFY_INLINE void *kmemdup(const void *p, size_t size, gfp_t gfp)
  {
  	size_t p_size = __builtin_object_size(p, 0);
  	if (__builtin_constant_p(size) && p_size < size)
  		__read_overflow();
  	if (p_size < size)
  		fortify_panic(__func__);
  	return __real_kmemdup(p, size, gfp);
  }
077d2ba51   Daniel Micay   replace incorrect...
463
464
465
466
467
468
469
  
  /* defined after fortified strlen and memcpy to reuse them */
  __FORTIFY_INLINE char *strcpy(char *p, const char *q)
  {
  	size_t p_size = __builtin_object_size(p, 0);
  	size_t q_size = __builtin_object_size(q, 0);
  	if (p_size == (size_t)-1 && q_size == (size_t)-1)
47227d27e   Daniel Axtens   string.h: fix inc...
470
  		return __underlying_strcpy(p, q);
077d2ba51   Daniel Micay   replace incorrect...
471
472
473
  	memcpy(p, q, strlen(q) + 1);
  	return p;
  }
47227d27e   Daniel Axtens   string.h: fix inc...
474
475
476
477
478
479
480
481
482
483
484
  /* Don't use these outside the FORITFY_SOURCE implementation */
  #undef __underlying_memchr
  #undef __underlying_memcmp
  #undef __underlying_memcpy
  #undef __underlying_memmove
  #undef __underlying_memset
  #undef __underlying_strcat
  #undef __underlying_strcpy
  #undef __underlying_strlen
  #undef __underlying_strncat
  #undef __underlying_strncpy
6974f0c45   Daniel Micay   include/linux/str...
485
  #endif
01f33c336   Martin Wilck   string.h: add mem...
486
487
488
489
490
491
492
493
  /**
   * memcpy_and_pad - Copy one buffer to another with padding
   * @dest: Where to copy to
   * @dest_len: The destination buffer size
   * @src: Where to copy from
   * @count: The number of bytes to copy
   * @pad: Character to use for padding if space is left in destination.
   */
1359798f9   Martin Wilck   string.h: un-fort...
494
495
  static inline void memcpy_and_pad(void *dest, size_t dest_len,
  				  const void *src, size_t count, int pad)
01f33c336   Martin Wilck   string.h: add mem...
496
  {
01f33c336   Martin Wilck   string.h: add mem...
497
498
499
500
501
502
  	if (dest_len > count) {
  		memcpy(dest, src, count);
  		memset(dest + count, pad,  dest_len - count);
  	} else
  		memcpy(dest, src, dest_len);
  }
72921427d   Steven Rostedt (VMware)   string.h: Add str...
503
504
505
506
507
508
509
510
511
512
513
  /**
   * str_has_prefix - Test if a string has a given prefix
   * @str: The string to test
   * @prefix: The string to see if @str starts with
   *
   * A common way to test a prefix of a string is to do:
   *  strncmp(str, prefix, sizeof(prefix) - 1)
   *
   * But this can lead to bugs due to typos, or if prefix is a pointer
   * and not a constant. Instead use str_has_prefix().
   *
917cda279   Joe Perches   kernel-doc: core-...
514
515
516
   * Returns:
   * * strlen(@prefix) if @str starts with @prefix
   * * 0 if @str does not start with @prefix
72921427d   Steven Rostedt (VMware)   string.h: Add str...
517
518
519
520
521
522
   */
  static __always_inline size_t str_has_prefix(const char *str, const char *prefix)
  {
  	size_t len = strlen(prefix);
  	return strncmp(str, prefix, len) == 0 ? len : 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
523
  #endif /* _LINUX_STRING_H_ */