summaryrefslogblamecommitdiff
path: root/libgcompat/string.c
blob: f2a2e87171b143fcbf1e6468092fcc7b08ecb080 (plain) (tree)
1
2
3
4
5
6
7
8
9
                                 
                                
                                          

                                      
                                
                                
                                                          
                 
                              
                                
 

                                   





                                                                         


                             


                                                          
                
                                                          
         

                                    

 





                                                                              


                             
                             
 
                                     

 





                                                      
 
                                     

 





                                                                          


                             





                                                          
 


































                                                                           
                 


                             
                            



























                                                                                

 






                                                               

                     


                             

                                           














                                                        

                                                               
                 
 

                             
                            





                                        


                                 
 
   







                                                                               
                                                       






                         









                                                    














                                                                 




                                                                            
 
                     


                             
                                               







                                            

 





                                                                          
 









                                        
 
 



                                                      
 
                                

 





                                                                               



                                                   









                                                             













                                 
                               



                         
                                                      
 


                                                         





                            
#define _GNU_SOURCE /* mempcpy */
#include <assert.h> /* assert */
#include <dlfcn.h>  /* dlsym, RTLD_NEXT */
#include <stddef.h> /* NULL, size_t */
#include <stdint.h> /* SIZE_MAX */
#include <stdlib.h> /* rand_r */
#define strerror_r no_strerror_r
#include <string.h> /* memcpy, strcpy, strncat, strndup */
#undef strerror_r
#include <time.h>   /* time */
#include <unistd.h> /* getpid */

#include "alias.h" /* weak_alias */

/**
 * Copy bytes in memory, with buffer overflow checking.
 *
 * LSB 5.0: LSB-Core-generic/baselib---memcpy-chk-1.html
 */
void *__memcpy_chk(void *dest, const void *src, size_t n, size_t destlen)
{
	assert(dest != NULL);
	assert(src != NULL);
	assert(destlen >= n);
	if (dest < src) {
		assert((char *) dest + n <= (char *) src);
	} else {
		assert((char *) src + n <= (char *) dest);
	}

	return memcpy(dest, src, n);
}

/**
 * Copy bytes in memory with overlapping areas, with buffer overflow checking.
 *
 * LSB 5.0: LSB-Core-generic/baselib---memmove-chk-1.html
 */
void *__memmove_chk(void *dest, const void *src, size_t n, size_t destlen)
{
	assert(dest != NULL);
	assert(src != NULL);
	assert(destlen >= n);

	return memmove(dest, src, n);
}

/**
 * Copy bytes in memory.
 *
 * LSB 5.0: LSB-Core-generic/baselib---mempcpy.html
 */
void *__mempcpy(void *dest, const void *src, size_t n)
{
	return mempcpy(dest, src, n);
}

/**
 * Copy bytes in memory, with buffer overflow checking.
 *
 * LSB 5.0: LSB-Core-generic/baselib---mempcpy-chk-1.html
 */
void *__mempcpy_chk(void *dest, const void *src, size_t n, size_t destlen)
{
	assert(dest != NULL);
	assert(src != NULL);
	assert(destlen >= n);
	if (dest < src) {
		assert((char *) dest + n <= (char *) src);
	} else {
		assert((char *) src + n <= (char *) dest);
	}

	return mempcpy(dest, src, n);
}

/**
 * Set bytes in memory, with buffer overflow checking.
 *
 * LSB 5.0: LSB-Core-generic/baselib---memset-chk-1.html
 */
void *__memset_chk(void *s, int c, size_t n, size_t buflen)
{
	assert(s != NULL);
	assert(buflen >= n);

	return memset(s, c, n);
}

/**
 * Find byte in memory.
 *
 * LSB 5.0: LSB-Core-generic/baselib---rawmemchr.html
 */
void *__rawmemchr(const void *s, int c)
{
	return memchr(s, c, SIZE_MAX);
}
weak_alias(__rawmemchr, rawmemchr);

/**
 * Copy a string and return a pointer to the end of the result, with buffer
 * overflow checking.
 *
 * LSB 5.0: LSB-Core-generic/baselib---stpcpy-chk-1.html
 */
char *__stpcpy_chk(char *dest, const char *src, size_t destlen)
{
	size_t n;

	assert(dest != NULL);
	assert(src != NULL);
	n = strlen(src) + 1;
	assert(destlen >= n);
	if (dest < src) {
		assert(dest + n <= src);
	} else {
		assert(src + n <= dest);
	}

	return stpcpy(dest, src);
}

/**
 * Copy a fixed-length string, returning a pointer to the array end, with buffer
 * overflow checking.
 *
 * LSB 5.0: LSB-Core-generic/baselib---stpncpy-chk-1.html
 */
char *__stpncpy_chk(char *dest, const char *src, size_t n, size_t destlen)
{
	assert(dest != NULL);
	assert(src != NULL);
	assert(destlen >= n);
	if (dest < src) {
		assert(dest + n <= src);
	} else {
		assert(src + n <= dest);
	}

	return stpncpy(dest, src, n);
}

/**
 * Concatenate two strings, with buffer overflow checking.
 *
 * LSB 5.0: LSB-Core-generic/baselib---strcat-chk-1.html
 */
char *__strcat_chk(char *dest, const char *src, size_t destlen)
{
	size_t n;
	size_t total;

	assert(dest != NULL);
	assert(src != NULL);
	n = strlen(src) + 1;
	total = strnlen(dest, destlen) + n;
	assert(destlen >= total);
	if (dest < src) {
		assert(dest + total <= src);
	} else {
		assert(src + n <= dest);
	}

	return strcat(dest, src);
}

/**
 * Copy a string, with buffer overflow checking.
 *
 * LSB 5.0: LSB-Core-generic/baselib---strcpy-chk-1.html
 */
char *__strcpy_chk(char *dest, const char *src, size_t destlen)
{
	size_t n;

	assert(dest != NULL);
	assert(src != NULL);
	n = strlen(src) + 1;
	assert(destlen >= n);
	if (dest < src) {
		assert(dest + n <= src);
	} else {
		assert(src + n <= dest);
	}

	return strcpy(dest, src);
}

/**
 * Find the substring length of a string that does not have any two characters.
 *
 * Not defined in LSB 5.0.  Used by spotify-client.
 */
size_t __strcspn_c2(const char *str, int bad, int bad2)
{
	size_t length = 0;
	const char *s = str;
	while (*s != bad && *s != bad2 && *s != '\0') {
		length++;
		s++;
	}
	return length;
}

/**
 * Alias for strdup.
 *
 * LSB 5.0: LSB-Core-generic/baselib---strdup-1.html
 */
char *__strdup(const char *string)
{
	return strdup(string);
}

/**
 * Non-POSIX strerror_r.
 */
static int (*real_strerror_r)(int, char *, size_t);

char *strerror_r(int errnum, char *buf, size_t buflen)
{
	if (real_strerror_r == NULL) {
		real_strerror_r = dlsym(RTLD_NEXT, "strerror_r");
		assert(real_strerror_r);
	}
	real_strerror_r(errnum, buf, buflen);
	return buf;
}

/**
 * Concatenate a string with part of another, with buffer overflow checking.
 *
 * LSB 5.0: LSB-Core-generic/baselib---strncat-chk-1.html
 */
char *__strncat_chk(char *dest, const char *src, size_t n, size_t destlen)
{
	size_t total;

	assert(dest != NULL);
	assert(src != NULL);
	total = strnlen(dest, destlen) + n + 1;
	assert(destlen >= total);
	if (dest < src) {
		assert(dest + total <= src);
	} else {
		assert(src + n <= dest);
	}

	return strncat(dest, src, n);
}

/**
 * Copy a fixed-length string, with buffer overflow checking.
 *
 * LSB 5.0: LSB-Core-generic/baselib---strncpy-chk-1.html
 */
char *__strncpy_chk(char *dest, const char *src, size_t n, size_t destlen)
{
	assert(dest != NULL);
	assert(src != NULL);
	assert(destlen >= n);
	if (dest < src) {
		assert(dest + n <= src);
	} else {
		assert(src + n <= dest);
	}

	return strncpy(dest, src, n);
}

/**
 * Duplicate a specific number of bytes from a string.
 */
char *__strndup(const char *s, size_t size)
{
	return strndup(s, size);
}

/**
 * Extract token from string.
 *
 * The "global" definition of strsep in glibc, used when architecture dependent
 * assembler versions aren't good enough.
 */
char *__strsep_g(char **stringp, const char *delim)
{
	return strsep(stringp, delim);
}

/**
 * Split string into tokens.
 *
 * LSB 5.0: LSB-Core-generic/baselib---strtok-r-1.html
 */
char *__strtok_r(char *s, const char *delim, char **save_ptr)
{
	return strtok_r(s, delim, save_ptr);
}

void *memfrob(void *s, size_t n)
{
	unsigned char *c = s;

	while (n--)
		*c++ ^= 42;

	return s;
}

char *strfry(char *s)
{
	static unsigned int seed;
	size_t len = strlen(s);

	if (!len)
		return s;

	seed += time(NULL) ^ getpid() ^ (uintptr_t) s;

	for (size_t i = 0; i < len - 1; ++i) {
		size_t j = rand_r(&seed) % (len - i) + i;
		char t = s[i];
		s[i] = s[j];
		s[j] = t;
	}

	return s;
}