/* * blunder -- detect and fix misues of strncpy and strncat. * * Copyright (C) 2004 David Collier-Brown * * This program is free software; you can redistribute it and/or modify * it under the terms of your choice of the GNU Lesser (Library) General * Public License or the Sun Common Development and Distribution License. */ #include /* For putenv. */ #include /* For strncpy/strncat. */ #include /* For strncpy/strncat. */ #include /* For gepid(). */ #include /* For fprintf(). */ #include /* For vsnprintf(). */ #ifdef undef #include /* For dlopen(). */ #include #endif static char *ProgName = "blunder.so.1"; void reportError(void); #define MAXLINE 1024 /* * strncpy -- copy strings up to N characters */ char * strncpy(char *dest, const char *src, size_t destsize) { unsigned len; if ((len = strlcpy(dest, src, destsize)) >= destsize) { (void) fprintf(stderr, "%s: " "error in strncpy(0x%p, \"%s\", %d)\n", ProgName, (void *)dest, src, destsize); if (len == destsize) { (void) fprintf(stderr, " " "Attempt to create a " "string exactly %d long, " "which will be unterminated.\n", destsize); } else { (void) fprintf(stderr, " " "Atempt to overflow dest string.\n"); } (void) fprintf(stderr, " " "Truncated to %d characters and " "null-terminated.\n", destsize-1); (void) reportError(); } return dest; } /* * strncat -- concatente strings up to N characters. */ char * strncat(char *dest, const char *src, size_t destsize) { int len; if ((len = strlcat(dest, src, destsize)) >= destsize) { (void) fprintf(stderr, "%s: " "error in strncat(0x%p, \"%s\", %d)\n", ProgName, (void *)dest, src, destsize); if (len == destsize) { (void) fprintf(stderr, " " "Attempt to create a " "string exactly %d long, " "which will be unterminated.\n", destsize); } else { (void) fprintf(stderr, " " "Atempt to overflow dest string.\n"); } (void) fprintf(stderr, " " "Truncated to %d characters and " "null-terminated.\n", destsize-1); reportError(); } return dest; } /* * strnprintf -- just do the reporting, as the size limitation * is already done. */ int snprintf(char *place, unsigned int size, const char *format, ...) { va_list ap; int rc; va_start(ap, format); if ((rc = vsnprintf(place, size, format, ap)) >= size) { (void) fprintf(stderr, "%s: snprintf just tried " "to overflow the dest string.\n" " Truncated to %d characters and " "null-terminated.\n", ProgName, size-1); reportError(); } va_end(ap); return rc; } /* * reportError -- tell the world what hapened and where. */ static void reportError(void) { pid_t pid; char procCmd[MAXLINE], oldEnv[MAXLINE]; static int nCores = 1; pid = getpid(); (void) snprintf(oldEnv, MAXLINE, "LD_PRELOAD=%s", getenv("LD_PRELOAD")); (void) putenv("LD_PRELOAD="); (void) fprintf(stderr, "%s: attempted string overflow in " " process %ld.\n" " Information follows, and a core will be\n" " written to /usr/tmp/blunder_core.%d.%ld\n", ProgName, pid, nCores, pid); (void) fprintf(stderr, "\npstack:\n"); (void) snprintf(procCmd, (int)sizeof(procCmd), "pstack %ld 1>&2'", pid); (void) system(procCmd); (void) fprintf(stderr, "\npmap:\n"); (void) snprintf(procCmd, (int)sizeof(procCmd), "pmap -x %ld 1>&2", pid); (void) system(procCmd); (void) fprintf(stderr, "\npsig:\n"); (void) snprintf(procCmd, (int)sizeof(procCmd), "psig %ld 1>&2", pid); (void) system(procCmd); (void) fprintf(stderr, "\npfiles:\n"); (void) snprintf(procCmd, (int)sizeof(procCmd), "pfiles %ld 1>&2", pid); (void) system(procCmd); (void) fprintf(stderr, "\npwdx:\n"); (void) snprintf(procCmd, (int)sizeof(procCmd), "pwdx %ld 1>&2", pid); (void) system(procCmd); (void) fprintf(stderr, "\nptree:\n"); (void) snprintf(procCmd, (int)sizeof(procCmd), "ptree %ld 1>&2", pid); (void) system(procCmd); (void) fprintf(stderr, "\nsaving core to /var/tmp/blunder_core.%d.%ld\n", nCores, pid); (void) snprintf(procCmd, (int)sizeof(procCmd), "gcore -o /var/tmp/blunder_core.%d %ld 1>&2", nCores, pid); (void) system(procCmd); (void) fprintf(stderr, "\n"); nCores++; (void) putenv(oldEnv); return; }