1/* Mudflap: narrow-pointer bounds-checking by tree rewriting.
2   Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
3   Contributed by Frank Ch. Eigler <fche@redhat.com>
4   and Graydon Hoare <graydon@redhat.com>
5
6This file is part of GCC.
7
8GCC is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
10Software Foundation; either version 2, or (at your option) any later
11version.
12
13In addition to the permissions in the GNU General Public License, the
14Free Software Foundation gives you unlimited permission to link the
15compiled version of this file into combinations with other programs,
16and to distribute those combinations without any restriction coming
17from the use of this file.  (The General Public License restrictions
18do apply in other respects; for example, they cover modification of
19the file, and distribution when not linked into a combine
20executable.)
21
22GCC is distributed in the hope that it will be useful, but WITHOUT ANY
23WARRANTY; without even the implied warranty of MERCHANTABILITY or
24FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
25for more details.
26
27You should have received a copy of the GNU General Public License
28along with GCC; see the file COPYING.  If not, write to the Free
29Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
3002110-1301, USA.  */
31
32
33#include "config.h"
34
35#ifndef HAVE_SOCKLEN_T
36#define socklen_t int
37#endif
38
39/* These attempt to coax various unix flavours to declare all our
40   needed tidbits in the system headers.  */
41#if !defined(__FreeBSD__) && !defined(__APPLE__)
42#define _POSIX_SOURCE
43#endif /* Some BSDs break <sys/socket.h> if this is defined. */
44#define _GNU_SOURCE
45#define _XOPEN_SOURCE
46#define _BSD_TYPES
47#define __EXTENSIONS__
48#define _ALL_SOURCE
49#define _LARGE_FILE_API
50#define _LARGEFILE64_SOURCE
51#define _XOPEN_SOURCE_EXTENDED 1
52
53#include <string.h>
54#include <stdarg.h>
55#include <stdio.h>
56#include <stdlib.h>
57#include <sys/stat.h>
58#include <sys/time.h>
59#include <sys/types.h>
60#include <unistd.h>
61#include <assert.h>
62#include <errno.h>
63#include <limits.h>
64#include <time.h>
65#include <ctype.h>
66#ifdef HAVE_DLFCN_H
67#include <dlfcn.h>
68#endif
69#ifdef HAVE_DIRENT_H
70#include <dirent.h>
71#endif
72#ifdef HAVE_SYS_SOCKET_H
73#include <sys/socket.h>
74#endif
75#ifdef HAVE_NETDB_H
76#include <netdb.h>
77#endif
78#ifdef HAVE_SYS_WAIT_H
79#include <sys/wait.h>
80#endif
81#ifdef HAVE_SYS_IPC_H
82#include <sys/ipc.h>
83#endif
84#ifdef HAVE_SYS_SEM_H
85#include <sys/sem.h>
86#endif
87#ifdef HAVE_SYS_SHM_H
88#include <sys/shm.h>
89#endif
90#ifdef HAVE_PWD_H
91#include <pwd.h>
92#endif
93#ifdef HAVE_GRP_H
94#include <grp.h>
95#endif
96#ifdef HAVE_MNTENT_H
97#include <mntent.h>
98#endif
99#ifdef HAVE_SYS_SOCKET_H
100#include <sys/socket.h>
101#endif
102#ifdef HAVE_NETINET_IN_H
103#include <netinet/in.h>
104#endif
105#ifdef HAVE_ARPA_INET_H
106#include <arpa/inet.h>
107#endif
108
109#include "mf-runtime.h"
110#include "mf-impl.h"
111
112#ifdef _MUDFLAP
113#error "Do not compile this file with -fmudflap!"
114#endif
115
116
117/* A bunch of independent stdlib/unistd hook functions, all
118   intercepted by mf-runtime.h macros.  */
119
120#ifndef HAVE_STRNLEN
121static inline size_t (strnlen) (const char* str, size_t n)
122{
123  const char *s;
124
125  for (s = str; n && *s; ++s, --n)
126    ;
127  return (s - str);
128}
129#endif
130
131
132/* str*,mem*,b* */
133
134WRAPPER2(void *, memcpy, void *dest, const void *src, size_t n)
135{
136  TRACE ("%s\n", __PRETTY_FUNCTION__);
137  MF_VALIDATE_EXTENT(src, n, __MF_CHECK_READ, "memcpy source");
138  MF_VALIDATE_EXTENT(dest, n, __MF_CHECK_WRITE, "memcpy dest");
139  return memcpy (dest, src, n);
140}
141
142
143WRAPPER2(void *, memmove, void *dest, const void *src, size_t n)
144{
145  TRACE ("%s\n", __PRETTY_FUNCTION__);
146  MF_VALIDATE_EXTENT(src, n, __MF_CHECK_READ, "memmove src");
147  MF_VALIDATE_EXTENT(dest, n, __MF_CHECK_WRITE, "memmove dest");
148  return memmove (dest, src, n);
149}
150
151
152WRAPPER2(void *, memset, void *s, int c, size_t n)
153{
154  TRACE ("%s\n", __PRETTY_FUNCTION__);
155  MF_VALIDATE_EXTENT(s, n, __MF_CHECK_WRITE, "memset dest");
156  return memset (s, c, n);
157}
158
159
160WRAPPER2(int, memcmp, const void *s1, const void *s2, size_t n)
161{
162  TRACE ("%s\n", __PRETTY_FUNCTION__);
163  MF_VALIDATE_EXTENT(s1, n, __MF_CHECK_READ, "memcmp 1st arg");
164  MF_VALIDATE_EXTENT(s2, n, __MF_CHECK_READ, "memcmp 2nd arg");
165  return memcmp (s1, s2, n);
166}
167
168
169WRAPPER2(void *, memchr, const void *s, int c, size_t n)
170{
171  TRACE ("%s\n", __PRETTY_FUNCTION__);
172  MF_VALIDATE_EXTENT(s, n, __MF_CHECK_READ, "memchr region");
173  return memchr (s, c, n);
174}
175
176
177#ifdef HAVE_MEMRCHR
178WRAPPER2(void *, memrchr, const void *s, int c, size_t n)
179{
180  TRACE ("%s\n", __PRETTY_FUNCTION__);
181  MF_VALIDATE_EXTENT(s, n, __MF_CHECK_READ, "memrchr region");
182  return memrchr (s, c, n);
183}
184#endif
185
186
187WRAPPER2(char *, strcpy, char *dest, const char *src)
188{
189  /* nb: just because strlen(src) == n doesn't mean (src + n) or (src + n +
190     1) are valid pointers. the allocated object might have size < n.
191     check anyways. */
192
193  size_t n = strlen (src);
194  TRACE ("%s\n", __PRETTY_FUNCTION__);
195  MF_VALIDATE_EXTENT(src, CLAMPADD(n, 1), __MF_CHECK_READ, "strcpy src");
196  MF_VALIDATE_EXTENT(dest, CLAMPADD(n, 1), __MF_CHECK_WRITE, "strcpy dest");
197  return strcpy (dest, src);
198}
199
200
201#ifdef HAVE_STRNCPY
202WRAPPER2(char *, strncpy, char *dest, const char *src, size_t n)
203{
204  size_t len = strnlen (src, n);
205  TRACE ("%s\n", __PRETTY_FUNCTION__);
206  MF_VALIDATE_EXTENT(src, len, __MF_CHECK_READ, "strncpy src");
207  MF_VALIDATE_EXTENT(dest, len, __MF_CHECK_WRITE, "strncpy dest"); /* nb: strNcpy */
208  return strncpy (dest, src, n);
209}
210#endif
211
212
213WRAPPER2(char *, strcat, char *dest, const char *src)
214{
215  size_t dest_sz;
216  size_t src_sz;
217  TRACE ("%s\n", __PRETTY_FUNCTION__);
218  dest_sz = strlen (dest);
219  src_sz = strlen (src);
220  MF_VALIDATE_EXTENT(src, CLAMPADD(src_sz, 1), __MF_CHECK_READ, "strcat src");
221  MF_VALIDATE_EXTENT(dest, CLAMPADD(dest_sz, CLAMPADD(src_sz, 1)),
222		     __MF_CHECK_WRITE, "strcat dest");
223  return strcat (dest, src);
224}
225
226
227WRAPPER2(char *, strncat, char *dest, const char *src, size_t n)
228{
229
230  /* nb: validating the extents (s,n) might be a mistake for two reasons.
231
232  (1) the string s might be shorter than n chars, and n is just a
233  poor choice by the programmer. this is not a "true" error in the
234  sense that the call to strncat would still be ok.
235
236  (2) we could try to compensate for case (1) by calling strlen(s) and
237  using that as a bound for the extent to verify, but strlen might fall off
238  the end of a non-terminated string, leading to a false positive.
239
240  so we will call strnlen(s,n) and use that as a bound.
241
242  if strnlen returns a length beyond the end of the registered extent
243  associated with s, there is an error: the programmer's estimate for n is
244  too large _AND_ the string s is unterminated, in which case they'd be
245  about to touch memory they don't own while calling strncat.
246
247  this same logic applies to further uses of strnlen later down in this
248  file. */
249
250  size_t src_sz;
251  size_t dest_sz;
252  TRACE ("%s\n", __PRETTY_FUNCTION__);
253  src_sz = strnlen (src, n);
254  dest_sz = strnlen (dest, n);
255  MF_VALIDATE_EXTENT(src, src_sz, __MF_CHECK_READ, "strncat src");
256  MF_VALIDATE_EXTENT(dest, (CLAMPADD(dest_sz, CLAMPADD(src_sz, 1))),
257		     __MF_CHECK_WRITE, "strncat dest");
258  return strncat (dest, src, n);
259}
260
261
262WRAPPER2(int, strcmp, const char *s1, const char *s2)
263{
264  size_t s1_sz;
265  size_t s2_sz;
266  TRACE ("%s\n", __PRETTY_FUNCTION__);
267  s1_sz = strlen (s1);
268  s2_sz = strlen (s2);
269  MF_VALIDATE_EXTENT(s1, CLAMPADD(s1_sz, 1), __MF_CHECK_READ, "strcmp 1st arg");
270  MF_VALIDATE_EXTENT(s2, CLAMPADD(s2_sz, 1), __MF_CHECK_WRITE, "strcmp 2nd arg");
271  return strcmp (s1, s2);
272}
273
274
275WRAPPER2(int, strcasecmp, const char *s1, const char *s2)
276{
277  size_t s1_sz;
278  size_t s2_sz;
279  TRACE ("%s\n", __PRETTY_FUNCTION__);
280  s1_sz = strlen (s1);
281  s2_sz = strlen (s2);
282  MF_VALIDATE_EXTENT(s1, CLAMPADD(s1_sz, 1), __MF_CHECK_READ, "strcasecmp 1st arg");
283  MF_VALIDATE_EXTENT(s2, CLAMPADD(s2_sz, 1), __MF_CHECK_READ, "strcasecmp 2nd arg");
284  return strcasecmp (s1, s2);
285}
286
287
288WRAPPER2(int, strncmp, const char *s1, const char *s2, size_t n)
289{
290  size_t s1_sz;
291  size_t s2_sz;
292  TRACE ("%s\n", __PRETTY_FUNCTION__);
293  s1_sz = strnlen (s1, n);
294  s2_sz = strnlen (s2, n);
295  MF_VALIDATE_EXTENT(s1, s1_sz, __MF_CHECK_READ, "strncmp 1st arg");
296  MF_VALIDATE_EXTENT(s2, s2_sz, __MF_CHECK_READ, "strncmp 2nd arg");
297  return strncmp (s1, s2, n);
298}
299
300
301WRAPPER2(int, strncasecmp, const char *s1, const char *s2, size_t n)
302{
303  size_t s1_sz;
304  size_t s2_sz;
305  TRACE ("%s\n", __PRETTY_FUNCTION__);
306  s1_sz = strnlen (s1, n);
307  s2_sz = strnlen (s2, n);
308  MF_VALIDATE_EXTENT(s1, s1_sz, __MF_CHECK_READ, "strncasecmp 1st arg");
309  MF_VALIDATE_EXTENT(s2, s2_sz, __MF_CHECK_READ, "strncasecmp 2nd arg");
310  return strncasecmp (s1, s2, n);
311}
312
313
314WRAPPER2(char *, strdup, const char *s)
315{
316  DECLARE(void *, malloc, size_t sz);
317  char *result;
318  size_t n = strlen (s);
319  TRACE ("%s\n", __PRETTY_FUNCTION__);
320  MF_VALIDATE_EXTENT(s, CLAMPADD(n,1), __MF_CHECK_READ, "strdup region");
321  result = (char *)CALL_REAL(malloc,
322			     CLAMPADD(CLAMPADD(n,1),
323				      CLAMPADD(__mf_opts.crumple_zone,
324					       __mf_opts.crumple_zone)));
325
326  if (UNLIKELY(! result)) return result;
327
328  result += __mf_opts.crumple_zone;
329  memcpy (result, s, n);
330  result[n] = '\0';
331
332  __mf_register (result, CLAMPADD(n,1), __MF_TYPE_HEAP_I, "strdup region");
333  return result;
334}
335
336
337WRAPPER2(char *, strndup, const char *s, size_t n)
338{
339  DECLARE(void *, malloc, size_t sz);
340  char *result;
341  size_t sz = strnlen (s, n);
342  TRACE ("%s\n", __PRETTY_FUNCTION__);
343  MF_VALIDATE_EXTENT(s, sz, __MF_CHECK_READ, "strndup region"); /* nb: strNdup */
344
345  /* note: strndup still adds a \0, even with the N limit! */
346  result = (char *)CALL_REAL(malloc,
347			     CLAMPADD(CLAMPADD(n,1),
348				      CLAMPADD(__mf_opts.crumple_zone,
349					       __mf_opts.crumple_zone)));
350
351  if (UNLIKELY(! result)) return result;
352
353  result += __mf_opts.crumple_zone;
354  memcpy (result, s, n);
355  result[n] = '\0';
356
357  __mf_register (result, CLAMPADD(n,1), __MF_TYPE_HEAP_I, "strndup region");
358  return result;
359}
360
361
362WRAPPER2(char *, strchr, const char *s, int c)
363{
364  size_t n;
365  TRACE ("%s\n", __PRETTY_FUNCTION__);
366  n = strlen (s);
367  MF_VALIDATE_EXTENT(s, CLAMPADD(n,1), __MF_CHECK_READ, "strchr region");
368  return strchr (s, c);
369}
370
371
372WRAPPER2(char *, strrchr, const char *s, int c)
373{
374  size_t n;
375  TRACE ("%s\n", __PRETTY_FUNCTION__);
376  n = strlen (s);
377  MF_VALIDATE_EXTENT(s, CLAMPADD(n,1), __MF_CHECK_READ, "strrchr region");
378  return strrchr (s, c);
379}
380
381
382WRAPPER2(char *, strstr, const char *haystack, const char *needle)
383{
384  size_t haystack_sz;
385  size_t needle_sz;
386  TRACE ("%s\n", __PRETTY_FUNCTION__);
387  haystack_sz = strlen (haystack);
388  needle_sz = strlen (needle);
389  MF_VALIDATE_EXTENT(haystack, CLAMPADD(haystack_sz, 1), __MF_CHECK_READ, "strstr haystack");
390  MF_VALIDATE_EXTENT(needle, CLAMPADD(needle_sz, 1), __MF_CHECK_READ, "strstr needle");
391  return strstr (haystack, needle);
392}
393
394
395#ifdef HAVE_MEMMEM
396WRAPPER2(void *, memmem,
397	const void *haystack, size_t haystacklen,
398	const void *needle, size_t needlelen)
399{
400  TRACE ("%s\n", __PRETTY_FUNCTION__);
401  MF_VALIDATE_EXTENT(haystack, haystacklen, __MF_CHECK_READ, "memmem haystack");
402  MF_VALIDATE_EXTENT(needle, needlelen, __MF_CHECK_READ, "memmem needle");
403  return memmem (haystack, haystacklen, needle, needlelen);
404}
405#endif
406
407
408WRAPPER2(size_t, strlen, const char *s)
409{
410  size_t result = strlen (s);
411  TRACE ("%s\n", __PRETTY_FUNCTION__);
412  MF_VALIDATE_EXTENT(s, CLAMPADD(result, 1), __MF_CHECK_READ, "strlen region");
413  return result;
414}
415
416
417WRAPPER2(size_t, strnlen, const char *s, size_t n)
418{
419  size_t result = strnlen (s, n);
420  TRACE ("%s\n", __PRETTY_FUNCTION__);
421  MF_VALIDATE_EXTENT(s, result, __MF_CHECK_READ, "strnlen region");
422  return result;
423}
424
425
426WRAPPER2(void, bzero, void *s, size_t n)
427{
428  TRACE ("%s\n", __PRETTY_FUNCTION__);
429  MF_VALIDATE_EXTENT(s, n, __MF_CHECK_WRITE, "bzero region");
430  bzero (s, n);
431}
432
433
434#undef bcopy
435WRAPPER2(void, bcopy, const void *src, void *dest, size_t n)
436{
437  TRACE ("%s\n", __PRETTY_FUNCTION__);
438  MF_VALIDATE_EXTENT(src, n, __MF_CHECK_READ, "bcopy src");
439  MF_VALIDATE_EXTENT(dest, n, __MF_CHECK_WRITE, "bcopy dest");
440  bcopy (src, dest, n);
441}
442
443
444#undef bcmp
445WRAPPER2(int, bcmp, const void *s1, const void *s2, size_t n)
446{
447  TRACE ("%s\n", __PRETTY_FUNCTION__);
448  MF_VALIDATE_EXTENT(s1, n, __MF_CHECK_READ, "bcmp 1st arg");
449  MF_VALIDATE_EXTENT(s2, n, __MF_CHECK_READ, "bcmp 2nd arg");
450  return bcmp (s1, s2, n);
451}
452
453
454WRAPPER2(char *, index, const char *s, int c)
455{
456  size_t n = strlen (s);
457  TRACE ("%s\n", __PRETTY_FUNCTION__);
458  MF_VALIDATE_EXTENT(s, CLAMPADD(n, 1), __MF_CHECK_READ, "index region");
459  return index (s, c);
460}
461
462
463WRAPPER2(char *, rindex, const char *s, int c)
464{
465  size_t n = strlen (s);
466  TRACE ("%s\n", __PRETTY_FUNCTION__);
467  MF_VALIDATE_EXTENT(s, CLAMPADD(n, 1), __MF_CHECK_READ, "rindex region");
468  return rindex (s, c);
469}
470
471/* XXX:  stpcpy, memccpy */
472
473/* XXX: *printf,*scanf */
474
475/* XXX: setjmp, longjmp */
476
477WRAPPER2(char *, asctime, struct tm *tm)
478{
479  static char *reg_result = NULL;
480  char *result;
481  TRACE ("%s\n", __PRETTY_FUNCTION__);
482  MF_VALIDATE_EXTENT(tm, sizeof (struct tm), __MF_CHECK_READ, "asctime tm");
483  result = asctime (tm);
484  if (reg_result == NULL)
485    {
486      __mf_register (result, strlen (result)+1, __MF_TYPE_STATIC, "asctime string");
487      reg_result = result;
488    }
489  return result;
490}
491
492
493WRAPPER2(char *, ctime, const time_t *timep)
494{
495  static char *reg_result = NULL;
496  char *result;
497  TRACE ("%s\n", __PRETTY_FUNCTION__);
498  MF_VALIDATE_EXTENT(timep, sizeof (time_t), __MF_CHECK_READ, "ctime time");
499  result = ctime (timep);
500  if (reg_result == NULL)
501    {
502      /* XXX: what if asctime and ctime return the same static ptr? */
503      __mf_register (result, strlen (result)+1, __MF_TYPE_STATIC, "ctime string");
504      reg_result = result;
505    }
506  return result;
507}
508
509
510WRAPPER2(struct tm*, localtime, const time_t *timep)
511{
512  static struct tm *reg_result = NULL;
513  struct tm *result;
514  TRACE ("%s\n", __PRETTY_FUNCTION__);
515  MF_VALIDATE_EXTENT(timep, sizeof (time_t), __MF_CHECK_READ, "localtime time");
516  result = localtime (timep);
517  if (reg_result == NULL)
518    {
519      __mf_register (result, sizeof (struct tm), __MF_TYPE_STATIC, "localtime tm");
520      reg_result = result;
521    }
522  return result;
523}
524
525
526WRAPPER2(struct tm*, gmtime, const time_t *timep)
527{
528  static struct tm *reg_result = NULL;
529  struct tm *result;
530  TRACE ("%s\n", __PRETTY_FUNCTION__);
531  MF_VALIDATE_EXTENT(timep, sizeof (time_t), __MF_CHECK_READ, "gmtime time");
532  result = gmtime (timep);
533  if (reg_result == NULL)
534    {
535      __mf_register (result, sizeof (struct tm), __MF_TYPE_STATIC, "gmtime tm");
536      reg_result = result;
537    }
538  return result;
539}
540
541
542/* EL start */
543
544/* The following indicate if the result of the corresponding function
545 * should be explicitly un/registered by the wrapper
546*/
547
548#ifdef __FreeBSD__
549#define MF_REGISTER_fopen		__MF_TYPE_STATIC
550#else
551#undef  MF_REGISTER_fopen
552#endif
553#define MF_RESULT_SIZE_fopen		(sizeof (FILE))
554
555#undef  MF_REGISTER_opendir
556#define MF_RESULT_SIZE_opendir		0	/* (sizeof (DIR)) */
557#undef  MF_REGISTER_readdir
558#define MF_REGISTER_gethostbyname	__MF_TYPE_STATIC
559#undef  MF_REGISTER_gethostbyname_items
560#undef  MF_REGISTER_dlopen
561#undef  MF_REGISTER_dlerror
562#undef  MF_REGISTER_dlsym
563#define MF_REGISTER_shmat		__MF_TYPE_GUESS
564
565
566#include <time.h>
567WRAPPER2(time_t, time, time_t *timep)
568{
569  TRACE ("%s\n", __PRETTY_FUNCTION__);
570  if (NULL != timep)
571    MF_VALIDATE_EXTENT (timep, sizeof (*timep), __MF_CHECK_WRITE,
572      "time timep");
573  return time (timep);
574}
575
576
577WRAPPER2(char *, strerror, int errnum)
578{
579  char *p;
580  static char * last_strerror = NULL;
581
582  TRACE ("%s\n", __PRETTY_FUNCTION__);
583  p = strerror (errnum);
584  if (last_strerror != NULL)
585    __mf_unregister (last_strerror, 0, __MF_TYPE_STATIC);
586  if (NULL != p)
587    __mf_register (p, strlen (p) + 1, __MF_TYPE_STATIC, "strerror result");
588  last_strerror = p;
589  return p;
590}
591
592
593
594/* An auxiliary data structure for tracking the hand-made stdio
595   buffers we generate during the fopen/fopen64 hooks.  In a civilized
596   language, this would be a simple dynamically sized FILE*->char*
597   lookup table, but this is C and we get to do it by hand.  */
598struct mf_filebuffer
599{
600  FILE *file;
601  char *buffer;
602  struct mf_filebuffer *next;
603};
604static struct mf_filebuffer *mf_filebuffers = NULL;
605
606static void
607mkbuffer (FILE *f)
608{
609  /* Reset any buffer automatically provided by libc, since this may
610     have been done via mechanisms that libmudflap couldn't
611     intercept.  */
612  int rc;
613  size_t bufsize = BUFSIZ;
614  int bufmode;
615  char *buffer = malloc (bufsize);
616  struct mf_filebuffer *b = malloc (sizeof (struct mf_filebuffer));
617  assert ((buffer != NULL) && (b != NULL));
618
619  /* Link it into list.  */
620  b->file = f;
621  b->buffer = buffer;
622  b->next = mf_filebuffers;
623  mf_filebuffers = b;
624
625  /* Determine how the file is supposed to be buffered at the moment.  */
626  bufmode = fileno (f) == 2 ? _IONBF : (isatty (fileno (f)) ? _IOLBF : _IOFBF);
627
628  rc = setvbuf (f, buffer, bufmode, bufsize);
629  assert (rc == 0);
630}
631
632static void
633unmkbuffer (FILE *f)
634{
635  struct mf_filebuffer *b = mf_filebuffers;
636  struct mf_filebuffer **pb = & mf_filebuffers;
637  while (b != NULL)
638    {
639      if (b->file == f)
640        {
641          *pb = b->next;
642          free (b->buffer);
643          free (b);
644          return;
645        }
646      pb = & b->next;
647      b = b->next;
648    }
649}
650
651
652
653WRAPPER2(FILE *, fopen, const char *path, const char *mode)
654{
655  size_t n;
656  FILE *p;
657  TRACE ("%s\n", __PRETTY_FUNCTION__);
658
659  n = strlen (path);
660  MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "fopen path");
661
662  n = strlen (mode);
663  MF_VALIDATE_EXTENT (mode, CLAMPADD(n, 1), __MF_CHECK_READ, "fopen mode");
664
665  p = fopen (path, mode);
666  if (NULL != p) {
667#ifdef MF_REGISTER_fopen
668    __mf_register (p, sizeof (*p), MF_REGISTER_fopen, "fopen result");
669#endif
670    MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_WRITE, "fopen result");
671
672    mkbuffer (p);
673  }
674
675  return p;
676}
677
678
679WRAPPER2(int, setvbuf, FILE *stream, char *buf, int mode, size_t size)
680{
681  int rc = 0;
682  TRACE ("%s\n", __PRETTY_FUNCTION__);
683
684  MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE, "setvbuf stream");
685
686  unmkbuffer (stream);
687
688  if (buf != NULL)
689    MF_VALIDATE_EXTENT (buf, size, __MF_CHECK_WRITE, "setvbuf buffer");
690
691  /* Override the user only if it's an auto-allocated buffer request.  Otherwise
692     assume that the supplied buffer is already known to libmudflap.  */
693  if ((buf == NULL) && ((mode == _IOFBF) || (mode == _IOLBF)))
694    mkbuffer (stream);
695  else
696    rc = setvbuf (stream, buf, mode, size);
697
698  return rc;
699}
700
701
702#ifdef HAVE_SETBUF
703WRAPPER2(int, setbuf, FILE* stream, char *buf)
704{
705  return __mfwrap_setvbuf (stream, buf, buf ? _IOFBF : _IONBF, BUFSIZ);
706}
707#endif
708
709#ifdef HAVE_SETBUFFER
710WRAPPER2(int, setbuffer, FILE* stream, char *buf, size_t sz)
711{
712  return __mfwrap_setvbuf (stream, buf, buf ? _IOFBF : _IONBF, sz);
713}
714#endif
715
716#ifdef HAVE_SETLINEBUF
717WRAPPER2(int, setlinebuf, FILE* stream)
718{
719  return __mfwrap_setvbuf(stream, NULL, _IOLBF, 0);
720}
721#endif
722
723
724
725WRAPPER2(FILE *, fdopen, int fd, const char *mode)
726{
727  size_t n;
728  FILE *p;
729  TRACE ("%s\n", __PRETTY_FUNCTION__);
730
731  n = strlen (mode);
732  MF_VALIDATE_EXTENT (mode, CLAMPADD(n, 1), __MF_CHECK_READ, "fdopen mode");
733
734  p = fdopen (fd, mode);
735  if (NULL != p) {
736#ifdef MF_REGISTER_fopen
737    __mf_register (p, sizeof (*p), MF_REGISTER_fopen, "fdopen result");
738#endif
739    MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_WRITE, "fdopen result");
740
741    mkbuffer (p);
742  }
743
744  return p;
745}
746
747
748WRAPPER2(FILE *, freopen, const char *path, const char *mode, FILE *s)
749{
750  size_t n;
751  FILE *p;
752  TRACE ("%s\n", __PRETTY_FUNCTION__);
753
754  n = strlen (path);
755  MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "freopen path");
756
757  MF_VALIDATE_EXTENT (s, (sizeof (*s)), __MF_CHECK_WRITE, "freopen stream");
758  unmkbuffer (s);
759
760  n = strlen (mode);
761  MF_VALIDATE_EXTENT (mode, CLAMPADD(n, 1), __MF_CHECK_READ, "freopen mode");
762
763  p = freopen (path, mode, s);
764  if (NULL != p) {
765#ifdef MF_REGISTER_fopen
766    __mf_register (p, sizeof (*p), MF_REGISTER_fopen, "freopen result");
767#endif
768    MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_WRITE, "freopen result");
769
770    mkbuffer (p);
771  }
772
773  return p;
774}
775
776
777#ifdef HAVE_FOPEN64
778WRAPPER2(FILE *, fopen64, const char *path, const char *mode)
779{
780  size_t n;
781  FILE *p;
782  TRACE ("%s\n", __PRETTY_FUNCTION__);
783
784  n = strlen (path);
785  MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "fopen64 path");
786
787  n = strlen (mode);
788  MF_VALIDATE_EXTENT (mode, CLAMPADD(n, 1), __MF_CHECK_READ, "fopen64 mode");
789
790  p = fopen64 (path, mode);
791  if (NULL != p) {
792#ifdef MF_REGISTER_fopen
793    __mf_register (p, sizeof (*p), MF_REGISTER_fopen, "fopen64 result");
794#endif
795    MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_WRITE, "fopen64 result");
796
797    mkbuffer (p);
798  }
799
800  return p;
801}
802#endif
803
804
805#ifdef HAVE_FREOPEN64
806WRAPPER2(FILE *, freopen64, const char *path, const char *mode, FILE *s)
807{
808  size_t n;
809  FILE *p;
810  TRACE ("%s\n", __PRETTY_FUNCTION__);
811
812  n = strlen (path);
813  MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "freopen64 path");
814
815  MF_VALIDATE_EXTENT (s, (sizeof (*s)), __MF_CHECK_WRITE, "freopen64 stream");
816  unmkbuffer (s);
817
818  n = strlen (mode);
819  MF_VALIDATE_EXTENT (mode, CLAMPADD(n, 1), __MF_CHECK_READ, "freopen64 mode");
820
821  p = freopen (path, mode, s);
822  if (NULL != p) {
823#ifdef MF_REGISTER_fopen
824    __mf_register (p, sizeof (*p), MF_REGISTER_fopen, "freopen64 result");
825#endif
826    MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_WRITE, "freopen64 result");
827
828    mkbuffer (p);
829  }
830
831  return p;
832}
833#endif
834
835
836WRAPPER2(int, fclose, FILE *stream)
837{
838  int resp;
839  TRACE ("%s\n", __PRETTY_FUNCTION__);
840  MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
841    "fclose stream");
842  resp = fclose (stream);
843#ifdef MF_REGISTER_fopen
844  __mf_unregister (stream, sizeof (*stream), MF_REGISTER_fopen);
845#endif
846  unmkbuffer (stream);
847
848  return resp;
849}
850
851
852WRAPPER2(size_t, fread, void *ptr, size_t size, size_t nmemb, FILE *stream)
853{
854  TRACE ("%s\n", __PRETTY_FUNCTION__);
855  MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
856    "fread stream");
857  MF_VALIDATE_EXTENT (ptr, size * nmemb, __MF_CHECK_WRITE, "fread buffer");
858  return fread (ptr, size, nmemb, stream);
859}
860
861
862WRAPPER2(size_t, fwrite, const void *ptr, size_t size, size_t nmemb,
863	FILE *stream)
864{
865  TRACE ("%s\n", __PRETTY_FUNCTION__);
866  MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
867    "fwrite stream");
868  MF_VALIDATE_EXTENT (ptr, size * nmemb, __MF_CHECK_READ, "fwrite buffer");
869  return fwrite (ptr, size, nmemb, stream);
870}
871
872
873WRAPPER2(int, fgetc, FILE *stream)
874{
875  TRACE ("%s\n", __PRETTY_FUNCTION__);
876  MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
877    "fgetc stream");
878  return fgetc (stream);
879}
880
881
882WRAPPER2(char *, fgets, char *s, int size, FILE *stream)
883{
884  TRACE ("%s\n", __PRETTY_FUNCTION__);
885  MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
886    "fgets stream");
887  MF_VALIDATE_EXTENT (s, size, __MF_CHECK_WRITE, "fgets buffer");
888  return fgets (s, size, stream);
889}
890
891
892WRAPPER2(int, getc, FILE *stream)
893{
894  TRACE ("%s\n", __PRETTY_FUNCTION__);
895  MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
896    "getc stream");
897  return getc (stream);
898}
899
900
901WRAPPER2(char *, gets, char *s)
902{
903  TRACE ("%s\n", __PRETTY_FUNCTION__);
904  MF_VALIDATE_EXTENT (s, 1, __MF_CHECK_WRITE, "gets buffer");
905  /* Avoid link-time warning... */
906  s = fgets (s, INT_MAX, stdin);
907  if (NULL != s) {	/* better late than never */
908    size_t n = strlen (s);
909    MF_VALIDATE_EXTENT (s, CLAMPADD(n, 1), __MF_CHECK_WRITE, "gets buffer");
910  }
911  return s;
912}
913
914
915WRAPPER2(int, ungetc, int c, FILE *stream)
916{
917  TRACE ("%s\n", __PRETTY_FUNCTION__);
918  MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
919     "ungetc stream");
920  return ungetc (c, stream);
921}
922
923
924WRAPPER2(int, fputc, int c, FILE *stream)
925{
926  TRACE ("%s\n", __PRETTY_FUNCTION__);
927  MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
928    "fputc stream");
929  return fputc (c, stream);
930}
931
932
933WRAPPER2(int, fputs, const char *s, FILE *stream)
934{
935  size_t n;
936  TRACE ("%s\n", __PRETTY_FUNCTION__);
937  n = strlen (s);
938  MF_VALIDATE_EXTENT (s, CLAMPADD(n, 1), __MF_CHECK_READ, "fputs buffer");
939  MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
940    "fputs stream");
941  return fputs (s, stream);
942}
943
944
945WRAPPER2(int, putc, int c, FILE *stream)
946{
947  TRACE ("%s\n", __PRETTY_FUNCTION__);
948  MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
949    "putc stream");
950  return putc (c, stream);
951}
952
953
954WRAPPER2(int, puts, const char *s)
955{
956  size_t n;
957  TRACE ("%s\n", __PRETTY_FUNCTION__);
958  n = strlen (s);
959  MF_VALIDATE_EXTENT (s, CLAMPADD(n, 1), __MF_CHECK_READ, "puts buffer");
960  return puts (s);
961}
962
963
964WRAPPER2(void, clearerr, FILE *stream)
965{
966  TRACE ("%s\n", __PRETTY_FUNCTION__);
967  MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
968    "clearerr stream");
969  clearerr (stream);
970}
971
972
973WRAPPER2(int, feof, FILE *stream)
974{
975  TRACE ("%s\n", __PRETTY_FUNCTION__);
976  MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
977    "feof stream");
978  return feof (stream);
979}
980
981
982WRAPPER2(int, ferror, FILE *stream)
983{
984  TRACE ("%s\n", __PRETTY_FUNCTION__);
985  MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
986    "ferror stream");
987  return ferror (stream);
988}
989
990
991WRAPPER2(int, fileno, FILE *stream)
992{
993  TRACE ("%s\n", __PRETTY_FUNCTION__);
994  MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
995    "fileno stream");
996  return fileno (stream);
997}
998
999
1000WRAPPER2(int, printf, const char *format, ...)
1001{
1002  size_t n;
1003  va_list ap;
1004  int result;
1005  TRACE ("%s\n", __PRETTY_FUNCTION__);
1006  n = strlen (format);
1007  MF_VALIDATE_EXTENT (format, CLAMPADD(n, 1), __MF_CHECK_READ,
1008    "printf format");
1009  va_start (ap, format);
1010  result = vprintf (format, ap);
1011  va_end (ap);
1012  return result;
1013}
1014
1015
1016WRAPPER2(int, fprintf, FILE *stream, const char *format, ...)
1017{
1018  size_t n;
1019  va_list ap;
1020  int result;
1021  TRACE ("%s\n", __PRETTY_FUNCTION__);
1022  MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
1023    "fprintf stream");
1024  n = strlen (format);
1025  MF_VALIDATE_EXTENT (format, CLAMPADD(n, 1), __MF_CHECK_READ,
1026    "fprintf format");
1027  va_start (ap, format);
1028  result = vfprintf (stream, format, ap);
1029  va_end (ap);
1030  return result;
1031}
1032
1033
1034WRAPPER2(int, sprintf, char *str, const char *format, ...)
1035{
1036  size_t n;
1037  va_list ap;
1038  int result;
1039  TRACE ("%s\n", __PRETTY_FUNCTION__);
1040  MF_VALIDATE_EXTENT (str, 1, __MF_CHECK_WRITE, "sprintf str");
1041  n = strlen (format);
1042  MF_VALIDATE_EXTENT (format, CLAMPADD(n, 1), __MF_CHECK_READ,
1043    "sprintf format");
1044  va_start (ap, format);
1045  result = vsprintf (str, format, ap);
1046  va_end (ap);
1047  n = strlen (str);
1048  MF_VALIDATE_EXTENT (str, CLAMPADD(n, 1), __MF_CHECK_WRITE, "sprintf str");
1049  return result;
1050}
1051
1052
1053WRAPPER2(int, snprintf, char *str, size_t size, const char *format, ...)
1054{
1055  size_t n;
1056  va_list ap;
1057  int result;
1058  TRACE ("%s\n", __PRETTY_FUNCTION__);
1059  MF_VALIDATE_EXTENT (str, size, __MF_CHECK_WRITE, "snprintf str");
1060  n = strlen (format);
1061  MF_VALIDATE_EXTENT (format, CLAMPADD(n, 1), __MF_CHECK_READ,
1062    "snprintf format");
1063  va_start (ap, format);
1064  result = vsnprintf (str, size, format, ap);
1065  va_end (ap);
1066  return result;
1067}
1068
1069
1070WRAPPER2(int, vprintf,  const char *format, va_list ap)
1071{
1072  size_t n;
1073  TRACE ("%s\n", __PRETTY_FUNCTION__);
1074  n = strlen (format);
1075  MF_VALIDATE_EXTENT (format, CLAMPADD(n, 1), __MF_CHECK_READ,
1076    "vprintf format");
1077  return vprintf (format, ap);
1078}
1079
1080
1081WRAPPER2(int, vfprintf, FILE *stream, const char *format, va_list ap)
1082{
1083  size_t n;
1084  TRACE ("%s\n", __PRETTY_FUNCTION__);
1085  MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
1086    "vfprintf stream");
1087  n = strlen (format);
1088  MF_VALIDATE_EXTENT (format, CLAMPADD(n, 1), __MF_CHECK_READ,
1089    "vfprintf format");
1090  return vfprintf (stream, format, ap);
1091}
1092
1093
1094WRAPPER2(int, vsprintf, char *str, const char *format, va_list ap)
1095{
1096  size_t n;
1097  int result;
1098  TRACE ("%s\n", __PRETTY_FUNCTION__);
1099  MF_VALIDATE_EXTENT (str, 1, __MF_CHECK_WRITE, "vsprintf str");
1100  n = strlen (format);
1101  MF_VALIDATE_EXTENT (format, CLAMPADD(n, 1), __MF_CHECK_READ,
1102    "vsprintf format");
1103  result = vsprintf (str, format, ap);
1104  n = strlen (str);
1105  MF_VALIDATE_EXTENT (str, CLAMPADD(n, 1), __MF_CHECK_WRITE, "vsprintf str");
1106  return result;
1107}
1108
1109
1110WRAPPER2(int, vsnprintf, char *str, size_t size, const char *format,
1111	va_list ap)
1112{
1113  size_t n;
1114  TRACE ("%s\n", __PRETTY_FUNCTION__);
1115  MF_VALIDATE_EXTENT (str, size, __MF_CHECK_WRITE, "vsnprintf str");
1116  n = strlen (format);
1117  MF_VALIDATE_EXTENT (format, CLAMPADD(n, 1), __MF_CHECK_READ,
1118    "vsnprintf format");
1119  return vsnprintf (str, size, format, ap);
1120}
1121
1122
1123WRAPPER2(int , access, const char *path, int mode)
1124{
1125  size_t n;
1126  TRACE ("%s\n", __PRETTY_FUNCTION__);
1127  n = strlen (path);
1128  MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "access path");
1129  return access (path, mode);
1130}
1131
1132
1133WRAPPER2(int , remove, const char *path)
1134{
1135  size_t n;
1136  TRACE ("%s\n", __PRETTY_FUNCTION__);
1137  n = strlen (path);
1138  MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "remove path");
1139  return remove (path);
1140}
1141
1142
1143WRAPPER2(int, fflush, FILE *stream)
1144{
1145  TRACE ("%s\n", __PRETTY_FUNCTION__);
1146  if (stream != NULL)
1147    MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
1148                        "fflush stream");
1149  return fflush (stream);
1150}
1151
1152
1153WRAPPER2(int, fseek, FILE *stream, long offset, int whence)
1154{
1155  TRACE ("%s\n", __PRETTY_FUNCTION__);
1156  MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
1157    "fseek stream");
1158  return fseek (stream, offset, whence);
1159}
1160
1161
1162#ifdef HAVE_FSEEKO64
1163WRAPPER2(int, fseeko64, FILE *stream, off64_t offset, int whence)
1164{
1165  TRACE ("%s\n", __PRETTY_FUNCTION__);
1166  MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
1167    "fseeko64 stream");
1168  return fseeko64 (stream, offset, whence);
1169}
1170#endif
1171
1172
1173WRAPPER2(long, ftell, FILE *stream)
1174{
1175  TRACE ("%s\n", __PRETTY_FUNCTION__);
1176  MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
1177    "ftell stream");
1178  return ftell (stream);
1179}
1180
1181
1182#ifdef HAVE_FTELLO64
1183WRAPPER2(off64_t, ftello64, FILE *stream)
1184{
1185  TRACE ("%s\n", __PRETTY_FUNCTION__);
1186  MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
1187    "ftello64 stream");
1188  return ftello64 (stream);
1189}
1190#endif
1191
1192
1193WRAPPER2(void, rewind, FILE *stream)
1194{
1195  TRACE ("%s\n", __PRETTY_FUNCTION__);
1196  MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
1197    "rewind stream");
1198  rewind (stream);
1199}
1200
1201
1202WRAPPER2(int, fgetpos, FILE *stream, fpos_t *pos)
1203{
1204  TRACE ("%s\n", __PRETTY_FUNCTION__);
1205  MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
1206    "fgetpos stream");
1207  MF_VALIDATE_EXTENT (pos, sizeof (*pos), __MF_CHECK_WRITE, "fgetpos pos");
1208  return fgetpos (stream, pos);
1209}
1210
1211
1212WRAPPER2(int, fsetpos, FILE *stream, fpos_t *pos)
1213{
1214  TRACE ("%s\n", __PRETTY_FUNCTION__);
1215  MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
1216    "fsetpos stream");
1217  MF_VALIDATE_EXTENT (pos, sizeof (*pos), __MF_CHECK_READ, "fsetpos pos");
1218  return fsetpos (stream, pos);
1219}
1220
1221
1222WRAPPER2(int , stat, const char *path, struct stat *buf)
1223{
1224  size_t n;
1225  TRACE ("%s\n", __PRETTY_FUNCTION__);
1226  n = strlen (path);
1227  MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "stat path");
1228  MF_VALIDATE_EXTENT (buf, sizeof (*buf), __MF_CHECK_READ, "stat buf");
1229  return stat (path, buf);
1230}
1231
1232
1233#ifdef HAVE_STAT64
1234WRAPPER2(int , stat64, const char *path, struct stat64 *buf)
1235{
1236  size_t n;
1237  TRACE ("%s\n", __PRETTY_FUNCTION__);
1238  n = strlen (path);
1239  MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "stat64 path");
1240  MF_VALIDATE_EXTENT (buf, sizeof (*buf), __MF_CHECK_READ, "stat64 buf");
1241  return stat64 (path, buf);
1242}
1243#endif
1244
1245
1246WRAPPER2(int , fstat, int filedes, struct stat *buf)
1247{
1248  TRACE ("%s\n", __PRETTY_FUNCTION__);
1249  MF_VALIDATE_EXTENT (buf, sizeof (*buf), __MF_CHECK_READ, "fstat buf");
1250  return fstat (filedes, buf);
1251}
1252
1253
1254WRAPPER2(int , lstat, const char *path, struct stat *buf)
1255{
1256  size_t n;
1257  TRACE ("%s\n", __PRETTY_FUNCTION__);
1258  n = strlen (path);
1259  MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "lstat path");
1260  MF_VALIDATE_EXTENT (buf, sizeof (*buf), __MF_CHECK_READ, "lstat buf");
1261  return lstat (path, buf);
1262}
1263
1264
1265WRAPPER2(int , mkfifo, const char *path, mode_t mode)
1266{
1267  size_t n;
1268  TRACE ("%s\n", __PRETTY_FUNCTION__);
1269  n = strlen (path);
1270  MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "mkfifo path");
1271  return mkfifo (path, mode);
1272}
1273
1274
1275#ifdef HAVE_DIRENT_H
1276WRAPPER2(DIR *, opendir, const char *path)
1277{
1278  DIR *p;
1279  size_t n;
1280  TRACE ("%s\n", __PRETTY_FUNCTION__);
1281  n = strlen (path);
1282  MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "opendir path");
1283
1284  p = opendir (path);
1285  if (NULL != p) {
1286#ifdef MF_REGISTER_opendir
1287    __mf_register (p, MF_RESULT_SIZE_opendir, MF_REGISTER_opendir,
1288      "opendir result");
1289#endif
1290    MF_VALIDATE_EXTENT (p, MF_RESULT_SIZE_opendir, __MF_CHECK_WRITE,
1291      "opendir result");
1292  }
1293  return p;
1294}
1295
1296
1297WRAPPER2(int, closedir, DIR *dir)
1298{
1299  TRACE ("%s\n", __PRETTY_FUNCTION__);
1300  MF_VALIDATE_EXTENT (dir, 0, __MF_CHECK_WRITE, "closedir dir");
1301#ifdef MF_REGISTER_opendir
1302  __mf_unregister (dir, MF_RESULT_SIZE_opendir, MF_REGISTER_opendir);
1303#endif
1304  return closedir (dir);
1305}
1306
1307
1308WRAPPER2(struct dirent *, readdir, DIR *dir)
1309{
1310  struct dirent *p;
1311  TRACE ("%s\n", __PRETTY_FUNCTION__);
1312  MF_VALIDATE_EXTENT (dir, 0, __MF_CHECK_READ, "readdir dir");
1313  p = readdir (dir);
1314  if (NULL != p) {
1315#ifdef MF_REGISTER_readdir
1316    __mf_register (p, sizeof (*p), MF_REGISTER_readdir, "readdir result");
1317#endif
1318    MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_WRITE, "readdir result");
1319  }
1320  return p;
1321}
1322#endif
1323
1324
1325#ifdef HAVE_SYS_SOCKET_H
1326
1327WRAPPER2(int, recv, int s, void *buf, size_t len, int flags)
1328{
1329  TRACE ("%s\n", __PRETTY_FUNCTION__);
1330  MF_VALIDATE_EXTENT (buf, len, __MF_CHECK_WRITE, "recv buf");
1331  return recv (s, buf, len, flags);
1332}
1333
1334
1335WRAPPER2(int, recvfrom, int s, void *buf, size_t len, int flags,
1336		struct sockaddr *from, socklen_t *fromlen)
1337{
1338  TRACE ("%s\n", __PRETTY_FUNCTION__);
1339  MF_VALIDATE_EXTENT (buf, len, __MF_CHECK_WRITE, "recvfrom buf");
1340  MF_VALIDATE_EXTENT (from, (size_t)*fromlen, __MF_CHECK_WRITE,
1341    "recvfrom from");
1342  return recvfrom (s, buf, len, flags, from, fromlen);
1343}
1344
1345
1346WRAPPER2(int, recvmsg, int s, struct msghdr *msg, int flags)
1347{
1348  TRACE ("%s\n", __PRETTY_FUNCTION__);
1349  MF_VALIDATE_EXTENT (msg, sizeof (*msg), __MF_CHECK_WRITE, "recvmsg msg");
1350  return recvmsg (s, msg, flags);
1351}
1352
1353
1354WRAPPER2(int, send, int s, const void *msg, size_t len, int flags)
1355{
1356  TRACE ("%s\n", __PRETTY_FUNCTION__);
1357  MF_VALIDATE_EXTENT (msg, len, __MF_CHECK_READ, "send msg");
1358  return send (s, msg, len, flags);
1359}
1360
1361
1362WRAPPER2(int, sendto, int s, const void *msg, size_t len, int flags,
1363		const struct sockaddr *to, socklen_t tolen)
1364{
1365  TRACE ("%s\n", __PRETTY_FUNCTION__);
1366  MF_VALIDATE_EXTENT (msg, len, __MF_CHECK_READ, "sendto msg");
1367  MF_VALIDATE_EXTENT (to, (size_t)tolen, __MF_CHECK_WRITE, "sendto to");
1368  return sendto (s, msg, len, flags, to, tolen);
1369}
1370
1371
1372WRAPPER2(int, sendmsg, int s, const void *msg, int flags)
1373{
1374  TRACE ("%s\n", __PRETTY_FUNCTION__);
1375  MF_VALIDATE_EXTENT (msg, sizeof (*msg), __MF_CHECK_READ, "sendmsg msg");
1376  return sendmsg (s, msg, flags);
1377}
1378
1379
1380WRAPPER2(int, setsockopt, int s, int level, int optname, const void *optval,
1381	socklen_t optlen)
1382{
1383  TRACE ("%s\n", __PRETTY_FUNCTION__);
1384  MF_VALIDATE_EXTENT (optval, (size_t)optlen, __MF_CHECK_READ,
1385    "setsockopt optval");
1386  return setsockopt (s, level, optname, optval, optlen);
1387}
1388
1389
1390WRAPPER2(int, getsockopt, int s, int level, int optname, void *optval,
1391		socklen_t *optlen)
1392{
1393  TRACE ("%s\n", __PRETTY_FUNCTION__);
1394  MF_VALIDATE_EXTENT (optval, (size_t)*optlen, __MF_CHECK_WRITE,
1395    "getsockopt optval");
1396  return getsockopt (s, level, optname, optval, optlen);
1397}
1398
1399
1400WRAPPER2(int, accept, int s, struct  sockaddr *addr, socklen_t *addrlen)
1401{
1402  TRACE ("%s\n", __PRETTY_FUNCTION__);
1403  if (addr != NULL)
1404    MF_VALIDATE_EXTENT (addr, (size_t)*addrlen, __MF_CHECK_WRITE, "accept addr");
1405  return accept (s, addr, addrlen);
1406}
1407
1408
1409WRAPPER2(int, bind, int sockfd, struct  sockaddr *addr, socklen_t addrlen)
1410{
1411  TRACE ("%s\n", __PRETTY_FUNCTION__);
1412  MF_VALIDATE_EXTENT (addr, (size_t)addrlen, __MF_CHECK_WRITE, "bind addr");
1413  return bind (sockfd, addr, addrlen);
1414}
1415
1416
1417WRAPPER2(int, connect, int sockfd, const struct sockaddr  *addr,
1418	socklen_t addrlen)
1419{
1420  TRACE ("%s\n", __PRETTY_FUNCTION__);
1421  MF_VALIDATE_EXTENT (addr, (size_t)addrlen, __MF_CHECK_READ,
1422    "connect addr");
1423  return connect (sockfd, addr, addrlen);
1424}
1425
1426#endif /* HAVE_SYS_SOCKET_H */
1427
1428
1429WRAPPER2(int, gethostname, char *name, size_t len)
1430{
1431  TRACE ("%s\n", __PRETTY_FUNCTION__);
1432  MF_VALIDATE_EXTENT (name, len, __MF_CHECK_WRITE, "gethostname name");
1433  return gethostname (name, len);
1434}
1435
1436
1437#ifdef HAVE_SETHOSTNAME
1438WRAPPER2(int, sethostname, const char *name, size_t len)
1439{
1440  TRACE ("%s\n", __PRETTY_FUNCTION__);
1441  MF_VALIDATE_EXTENT (name, len, __MF_CHECK_READ, "sethostname name");
1442  return sethostname (name, len);
1443}
1444#endif
1445
1446
1447#ifdef HAVE_NETDB_H
1448
1449WRAPPER2(struct hostent *, gethostbyname, const char *name)
1450{
1451  struct hostent *p;
1452  char **ss;
1453  char *s;
1454  size_t n;
1455  int nreg;
1456  TRACE ("%s\n", __PRETTY_FUNCTION__);
1457  n = strlen (name);
1458  MF_VALIDATE_EXTENT (name, CLAMPADD(n, 1), __MF_CHECK_READ,
1459    "gethostbyname name");
1460  p = gethostbyname (name);
1461  if (NULL != p) {
1462#ifdef MF_REGISTER_gethostbyname
1463    __mf_register (p, sizeof (*p), MF_REGISTER_gethostbyname,
1464      "gethostbyname result");
1465#endif
1466    MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_WRITE,
1467      "gethostbyname result");
1468    if (NULL != (s = p->h_name)) {
1469      n = strlen (s);
1470      n = CLAMPADD(n, 1);
1471#ifdef MF_REGISTER_gethostbyname_items
1472      __mf_register (s, n, MF_REGISTER_gethostbyname_items,
1473        "gethostbyname result->h_name");
1474#endif
1475      MF_VALIDATE_EXTENT (s, n, __MF_CHECK_WRITE,
1476        "gethostbyname result->h_name");
1477    }
1478
1479    if (NULL != (ss = p->h_aliases)) {
1480      for (nreg = 1;; ++nreg) {
1481        s = *ss++;
1482        if (NULL == s)
1483          break;
1484        n = strlen (s);
1485        n = CLAMPADD(n, 1);
1486#ifdef MF_REGISTER_gethostbyname_items
1487        __mf_register (s, n, MF_REGISTER_gethostbyname_items,
1488          "gethostbyname result->h_aliases[]");
1489#endif
1490        MF_VALIDATE_EXTENT (s, n, __MF_CHECK_WRITE,
1491          "gethostbyname result->h_aliases[]");
1492      }
1493      nreg *= sizeof (*p->h_aliases);
1494#ifdef MF_REGISTER_gethostbyname_items
1495      __mf_register (p->h_aliases, nreg, MF_REGISTER_gethostbyname_items,
1496        "gethostbyname result->h_aliases");
1497#endif
1498      MF_VALIDATE_EXTENT (p->h_aliases, nreg, __MF_CHECK_WRITE,
1499        "gethostbyname result->h_aliases");
1500    }
1501
1502    if (NULL != (ss = p->h_addr_list)) {
1503      for (nreg = 1;; ++nreg) {
1504        s = *ss++;
1505        if (NULL == s)
1506          break;
1507#ifdef MF_REGISTER_gethostbyname_items
1508        __mf_register (s, p->h_length, MF_REGISTER_gethostbyname_items,
1509          "gethostbyname result->h_addr_list[]");
1510#endif
1511        MF_VALIDATE_EXTENT (s, p->h_length, __MF_CHECK_WRITE,
1512          "gethostbyname result->h_addr_list[]");
1513      }
1514      nreg *= sizeof (*p->h_addr_list);
1515#ifdef MF_REGISTER_gethostbyname_items
1516      __mf_register (p->h_addr_list, nreg, MF_REGISTER_gethostbyname_items,
1517        "gethostbyname result->h_addr_list");
1518#endif
1519      MF_VALIDATE_EXTENT (p->h_addr_list, nreg, __MF_CHECK_WRITE,
1520        "gethostbyname result->h_addr_list");
1521    }
1522  }
1523  return p;
1524}
1525
1526#endif /* HAVE_NETDB_H */
1527
1528
1529#ifdef HAVE_SYS_WAIT_H
1530
1531WRAPPER2(pid_t, wait, int *status)
1532{
1533  TRACE ("%s\n", __PRETTY_FUNCTION__);
1534  if (NULL != status)
1535    MF_VALIDATE_EXTENT (status, sizeof (*status), __MF_CHECK_WRITE,
1536      "wait status");
1537  return wait (status);
1538}
1539
1540
1541WRAPPER2(pid_t, waitpid, pid_t pid, int *status, int options)
1542{
1543  TRACE ("%s\n", __PRETTY_FUNCTION__);
1544  if (NULL != status)
1545    MF_VALIDATE_EXTENT (status, sizeof (*status), __MF_CHECK_WRITE,
1546      "waitpid status");
1547  return waitpid (pid, status, options);
1548}
1549
1550#endif /* HAVE_SYS_WAIT_H */
1551
1552
1553WRAPPER2(FILE *, popen, const char *command, const char *mode)
1554{
1555  size_t n;
1556  FILE *p;
1557  TRACE ("%s\n", __PRETTY_FUNCTION__);
1558
1559  n = strlen (command);
1560  MF_VALIDATE_EXTENT (command, CLAMPADD(n, 1), __MF_CHECK_READ, "popen path");
1561
1562  n = strlen (mode);
1563  MF_VALIDATE_EXTENT (mode, CLAMPADD(n, 1), __MF_CHECK_READ, "popen mode");
1564
1565  p = popen (command, mode);
1566  if (NULL != p) {
1567#ifdef MF_REGISTER_fopen
1568    __mf_register (p, sizeof (*p), MF_REGISTER_fopen, "popen result");
1569#endif
1570    MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_WRITE, "popen result");
1571  }
1572  return p;
1573}
1574
1575
1576WRAPPER2(int, pclose, FILE *stream)
1577{
1578  int resp;
1579  TRACE ("%s\n", __PRETTY_FUNCTION__);
1580  MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
1581    "pclose stream");
1582  resp = pclose (stream);
1583#ifdef MF_REGISTER_fopen
1584  __mf_unregister (stream, sizeof (*stream), MF_REGISTER_fopen);
1585#endif
1586  return resp;
1587}
1588
1589
1590WRAPPER2(int, execve, const char *path, char *const argv [],
1591	char *const envp[])
1592{
1593  size_t n;
1594  char *const *p;
1595  const char *s;
1596  TRACE ("%s\n", __PRETTY_FUNCTION__);
1597
1598  n = strlen (path);
1599  MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "execve path");
1600
1601  for (p = argv;;) {
1602    MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_READ, "execve *argv");
1603    s = *p++;
1604    if (NULL == s)
1605      break;
1606    n = strlen (s);
1607    MF_VALIDATE_EXTENT (s, CLAMPADD(n, 1), __MF_CHECK_READ, "execve **argv");
1608  }
1609
1610  for (p = envp;;) {
1611    MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_READ, "execve *envp");
1612    s = *p++;
1613    if (NULL == s)
1614      break;
1615    n = strlen (s);
1616    MF_VALIDATE_EXTENT (s, CLAMPADD(n, 1), __MF_CHECK_READ, "execve **envp");
1617  }
1618  return execve (path, argv, envp);
1619}
1620
1621
1622WRAPPER2(int, execv, const char *path, char *const argv [])
1623{
1624  size_t n;
1625  char *const *p;
1626  const char *s;
1627  TRACE ("%s\n", __PRETTY_FUNCTION__);
1628
1629  n = strlen (path);
1630  MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "execv path");
1631
1632  for (p = argv;;) {
1633    MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_READ, "execv *argv");
1634    s = *p++;
1635    if (NULL == s)
1636      break;
1637    n = strlen (s);
1638    MF_VALIDATE_EXTENT (s, CLAMPADD(n, 1), __MF_CHECK_READ, "execv **argv");
1639  }
1640  return execv (path, argv);
1641}
1642
1643
1644WRAPPER2(int, execvp, const char *path, char *const argv [])
1645{
1646  size_t n;
1647  char *const *p;
1648  const char *s;
1649  TRACE ("%s\n", __PRETTY_FUNCTION__);
1650
1651  n = strlen (path);
1652  MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "execvp path");
1653
1654  for (p = argv;;) {
1655    MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_READ, "execvp *argv");
1656    s = *p++;
1657    if (NULL == s)
1658      break;
1659    n = strlen (s);
1660    MF_VALIDATE_EXTENT (s, CLAMPADD(n, 1), __MF_CHECK_READ, "execvp **argv");
1661  }
1662  return execvp (path, argv);
1663}
1664
1665
1666WRAPPER2(int, system, const char *string)
1667{
1668  size_t n;
1669  TRACE ("%s\n", __PRETTY_FUNCTION__);
1670  n = strlen (string);
1671  MF_VALIDATE_EXTENT (string, CLAMPADD(n, 1), __MF_CHECK_READ,
1672    "system string");
1673  return system (string);
1674}
1675
1676
1677WRAPPER2(void *, dlopen, const char *path, int flags)
1678{
1679  void *p;
1680  size_t n;
1681  TRACE ("%s\n", __PRETTY_FUNCTION__);
1682  n = strlen (path);
1683  MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "dlopen path");
1684  p = dlopen (path, flags);
1685  if (NULL != p) {
1686#ifdef MF_REGISTER_dlopen
1687    __mf_register (p, 0, MF_REGISTER_dlopen, "dlopen result");
1688#endif
1689    MF_VALIDATE_EXTENT (p, 0, __MF_CHECK_WRITE, "dlopen result");
1690  }
1691  return p;
1692}
1693
1694
1695WRAPPER2(int, dlclose, void *handle)
1696{
1697  int resp;
1698  TRACE ("%s\n", __PRETTY_FUNCTION__);
1699  MF_VALIDATE_EXTENT (handle, 0, __MF_CHECK_READ, "dlclose handle");
1700  resp = dlclose (handle);
1701#ifdef MF_REGISTER_dlopen
1702  __mf_unregister (handle, 0, MF_REGISTER_dlopen);
1703#endif
1704  return resp;
1705}
1706
1707
1708WRAPPER2(char *, dlerror)
1709{
1710  char *p;
1711  TRACE ("%s\n", __PRETTY_FUNCTION__);
1712  p = dlerror ();
1713  if (NULL != p) {
1714    size_t n;
1715    n = strlen (p);
1716    n = CLAMPADD(n, 1);
1717#ifdef MF_REGISTER_dlerror
1718    __mf_register (p, n, MF_REGISTER_dlerror, "dlerror result");
1719#endif
1720    MF_VALIDATE_EXTENT (p, n, __MF_CHECK_WRITE, "dlerror result");
1721  }
1722  return p;
1723}
1724
1725
1726WRAPPER2(void *, dlsym, void *handle, char *symbol)
1727{
1728  size_t n;
1729  void *p;
1730  TRACE ("%s\n", __PRETTY_FUNCTION__);
1731  MF_VALIDATE_EXTENT (handle, 0, __MF_CHECK_READ, "dlsym handle");
1732  n = strlen (symbol);
1733  MF_VALIDATE_EXTENT (symbol, CLAMPADD(n, 1), __MF_CHECK_READ, "dlsym symbol");
1734  p = dlsym (handle, symbol);
1735  if (NULL != p) {
1736#ifdef MF_REGISTER_dlsym
1737    __mf_register (p, 0, MF_REGISTER_dlsym, "dlsym result");
1738#endif
1739    MF_VALIDATE_EXTENT (p, 0, __MF_CHECK_WRITE, "dlsym result");
1740  }
1741  return p;
1742}
1743
1744
1745#if defined (HAVE_SYS_IPC_H) && defined (HAVE_SYS_SEM_H) && defined (HAVE_SYS_SHM_H)
1746
1747WRAPPER2(int, semop, int semid, struct sembuf *sops, unsigned nsops)
1748{
1749  TRACE ("%s\n", __PRETTY_FUNCTION__);
1750  MF_VALIDATE_EXTENT (sops, sizeof (*sops) * nsops, __MF_CHECK_READ,
1751    "semop sops");
1752  return semop (semid, sops, nsops);
1753}
1754
1755
1756#ifndef HAVE_UNION_SEMUN
1757union semun {
1758	int val;			/* value for SETVAL */
1759	struct semid_ds *buf;		/* buffer for IPC_STAT, IPC_SET */
1760	unsigned short int *array;	/* array for GETALL, SETALL */
1761	struct seminfo *__buf;		/* buffer for IPC_INFO */
1762};
1763#endif
1764WRAPPER2(int, semctl, int semid, int semnum, int cmd, union semun arg)
1765{
1766  TRACE ("%s\n", __PRETTY_FUNCTION__);
1767  switch (cmd) {
1768  case IPC_STAT:
1769    MF_VALIDATE_EXTENT (arg.buf, sizeof (*arg.buf), __MF_CHECK_WRITE,
1770      "semctl buf");
1771    break;
1772  case IPC_SET:
1773    MF_VALIDATE_EXTENT (arg.buf, sizeof (*arg.buf), __MF_CHECK_READ,
1774      "semctl buf");
1775    break;
1776  case GETALL:
1777    MF_VALIDATE_EXTENT (arg.array, sizeof (*arg.array), __MF_CHECK_WRITE,
1778      "semctl array");
1779  case SETALL:
1780    MF_VALIDATE_EXTENT (arg.array, sizeof (*arg.array), __MF_CHECK_READ,
1781      "semctl array");
1782    break;
1783#ifdef IPC_INFO
1784  /* FreeBSD 5.1 And Cygwin headers include IPC_INFO but not the __buf field.  */
1785#if !defined(__FreeBSD__) && !defined(__CYGWIN__)
1786  case IPC_INFO:
1787    MF_VALIDATE_EXTENT (arg.__buf, sizeof (*arg.__buf), __MF_CHECK_WRITE,
1788      "semctl __buf");
1789    break;
1790#endif
1791#endif
1792  default:
1793    break;
1794  }
1795  return semctl (semid, semnum, cmd, arg);
1796}
1797
1798
1799WRAPPER2(int, shmctl, int shmid, int cmd, struct shmid_ds *buf)
1800{
1801  TRACE ("%s\n", __PRETTY_FUNCTION__);
1802  switch (cmd) {
1803  case IPC_STAT:
1804    MF_VALIDATE_EXTENT (buf, sizeof (*buf), __MF_CHECK_WRITE,
1805      "shmctl buf");
1806    break;
1807  case IPC_SET:
1808    MF_VALIDATE_EXTENT (buf, sizeof (*buf), __MF_CHECK_READ,
1809      "shmctl buf");
1810    break;
1811  default:
1812    break;
1813  }
1814  return shmctl (shmid, cmd, buf);
1815}
1816
1817
1818WRAPPER2(void *, shmat, int shmid, const void *shmaddr, int shmflg)
1819{
1820  void *p;
1821  TRACE ("%s\n", __PRETTY_FUNCTION__);
1822  p = shmat (shmid, shmaddr, shmflg);
1823#ifdef MF_REGISTER_shmat
1824  if (NULL != p) {
1825    struct shmid_ds buf;
1826    __mf_register (p, shmctl (shmid, IPC_STAT, &buf) ? 0 : buf.shm_segsz,
1827      MF_REGISTER_shmat, "shmat result");
1828  }
1829#endif
1830  return p;
1831}
1832
1833
1834WRAPPER2(int, shmdt, const void *shmaddr)
1835{
1836  int resp;
1837  TRACE ("%s\n", __PRETTY_FUNCTION__);
1838  resp = shmdt (shmaddr);
1839#ifdef MF_REGISTER_shmat
1840  __mf_unregister ((void *)shmaddr, 0, MF_REGISTER_shmat);
1841#endif
1842  return resp;
1843}
1844
1845
1846#endif /* HAVE_SYS_IPC/SEM/SHM_H */
1847
1848
1849
1850/* ctype stuff.  This is host-specific by necessity, as the arrays
1851   that is used by most is*()/to*() macros are implementation-defined.  */
1852
1853/* GLIBC 2.3 */
1854#ifdef HAVE___CTYPE_B_LOC
1855WRAPPER2(unsigned short **, __ctype_b_loc, void)
1856{
1857  static unsigned short * last_buf = (void *) 0;
1858  static unsigned short ** last_ptr = (void *) 0;
1859  unsigned short ** ptr = (unsigned short **) __ctype_b_loc ();
1860  unsigned short * buf = * ptr;
1861  if (ptr != last_ptr)
1862    {
1863      /* XXX: unregister last_ptr? */
1864      last_ptr = ptr;
1865      __mf_register (last_ptr, sizeof(last_ptr), __MF_TYPE_STATIC, "ctype_b_loc **");
1866    }
1867  if (buf != last_buf)
1868    {
1869      last_buf = buf;
1870      __mf_register ((void *) (last_buf - 128), 384 * sizeof(unsigned short), __MF_TYPE_STATIC,
1871                     "ctype_b_loc []");
1872    }
1873  return ptr;
1874}
1875#endif
1876
1877#ifdef HAVE___CTYPE_TOUPPER_LOC
1878WRAPPER2(int **, __ctype_toupper_loc, void)
1879{
1880  static int * last_buf = (void *) 0;
1881  static int ** last_ptr = (void *) 0;
1882  int ** ptr = (int **) __ctype_toupper_loc ();
1883  int * buf = * ptr;
1884  if (ptr != last_ptr)
1885    {
1886      /* XXX: unregister last_ptr? */
1887      last_ptr = ptr;
1888      __mf_register (last_ptr, sizeof(last_ptr), __MF_TYPE_STATIC, "ctype_toupper_loc **");
1889    }
1890  if (buf != last_buf)
1891    {
1892      last_buf = buf;
1893      __mf_register ((void *) (last_buf - 128), 384 * sizeof(int), __MF_TYPE_STATIC,
1894                     "ctype_toupper_loc []");
1895    }
1896  return ptr;
1897}
1898#endif
1899
1900#ifdef HAVE___CTYPE_TOLOWER_LOC
1901WRAPPER2(int **, __ctype_tolower_loc, void)
1902{
1903  static int * last_buf = (void *) 0;
1904  static int ** last_ptr = (void *) 0;
1905  int ** ptr = (int **) __ctype_tolower_loc ();
1906  int * buf = * ptr;
1907  if (ptr != last_ptr)
1908    {
1909      /* XXX: unregister last_ptr? */
1910      last_ptr = ptr;
1911      __mf_register (last_ptr, sizeof(last_ptr), __MF_TYPE_STATIC, "ctype_tolower_loc **");
1912    }
1913  if (buf != last_buf)
1914    {
1915      last_buf = buf;
1916      __mf_register ((void *) (last_buf - 128), 384 * sizeof(int), __MF_TYPE_STATIC,
1917                     "ctype_tolower_loc []");
1918    }
1919  return ptr;
1920}
1921#endif
1922
1923
1924/* passwd/group related functions.  These register every (static) pointer value returned,
1925   and rely on libmudflap's quiet toleration of duplicate static registrations.  */
1926
1927#ifdef HAVE_GETLOGIN
1928WRAPPER2(char *, getlogin, void)
1929{
1930  char *buf = getlogin ();
1931  if (buf != NULL)
1932    __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
1933                   "getlogin() return");
1934  return buf;
1935}
1936#endif
1937
1938
1939#ifdef HAVE_CUSERID
1940WRAPPER2(char *, cuserid, char * buf)
1941{
1942  if (buf != NULL)
1943    {
1944      MF_VALIDATE_EXTENT(buf, L_cuserid, __MF_CHECK_WRITE,
1945                         "cuserid destination");
1946      return cuserid (buf);
1947    }
1948  buf = cuserid (NULL);
1949  if (buf != NULL)
1950    __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
1951                   "getcuserid() return");
1952  return buf;
1953}
1954#endif
1955
1956
1957#ifdef HAVE_GETPWNAM
1958WRAPPER2(struct passwd *, getpwnam, const char *name)
1959{
1960  struct passwd *buf;
1961  MF_VALIDATE_EXTENT(name, strlen(name)+1, __MF_CHECK_READ,
1962                     "getpwnam name");
1963  buf = getpwnam (name);
1964  if (buf != NULL)
1965    __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
1966                   "getpw*() return");
1967  return buf;
1968}
1969#endif
1970
1971
1972#ifdef HAVE_GETPWUID
1973WRAPPER2(struct passwd *, getpwuid, uid_t uid)
1974{
1975  struct passwd *buf;
1976  buf = getpwuid (uid);
1977  if (buf != NULL)
1978    __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
1979                   "getpw*() return");
1980  return buf;
1981}
1982#endif
1983
1984
1985#ifdef HAVE_GETGRNAM
1986WRAPPER2(struct group *, getgrnam, const char *name)
1987{
1988  struct group *buf;
1989  MF_VALIDATE_EXTENT(name, strlen(name)+1, __MF_CHECK_READ,
1990                     "getgrnam name");
1991  buf = getgrnam (name);
1992  if (buf != NULL)
1993    __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
1994                   "getgr*() return");
1995  return buf;
1996}
1997#endif
1998
1999
2000#ifdef HAVE_GETGRGID
2001WRAPPER2(struct group *, getgrgid, uid_t uid)
2002{
2003  struct group *buf;
2004  buf = getgrgid (uid);
2005  if (buf != NULL)
2006    __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
2007                   "getgr*() return");
2008  return buf;
2009}
2010#endif
2011
2012
2013#ifdef HAVE_GETSERVENT
2014WRAPPER2(struct servent *, getservent, void)
2015{
2016  struct servent *buf;
2017  buf = getservent ();
2018  if (buf != NULL)
2019    __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
2020                   "getserv*() return");
2021  return buf;
2022}
2023#endif
2024
2025
2026#ifdef HAVE_GETSERVBYNAME
2027WRAPPER2(struct servent *, getservbyname, const char *name, const char *proto)
2028{
2029  struct servent *buf;
2030  MF_VALIDATE_EXTENT(name, strlen(name)+1, __MF_CHECK_READ,
2031                     "getservbyname name");
2032  MF_VALIDATE_EXTENT(proto, strlen(proto)+1, __MF_CHECK_READ,
2033                     "getservbyname proto");
2034  buf = getservbyname (name, proto);
2035  if (buf != NULL)
2036    __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
2037                   "getserv*() return");
2038  return buf;
2039}
2040#endif
2041
2042
2043#ifdef HAVE_GETSERVBYPORT
2044WRAPPER2(struct servent *, getservbyport, int port, const char *proto)
2045{
2046  struct servent *buf;
2047  MF_VALIDATE_EXTENT(proto, strlen(proto)+1, __MF_CHECK_READ,
2048                     "getservbyport proto");
2049  buf = getservbyport (port, proto);
2050  if (buf != NULL)
2051    __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
2052                   "getserv*() return");
2053  return buf;
2054}
2055#endif
2056
2057
2058#ifdef HAVE_GAI_STRERROR
2059WRAPPER2(const char *, gai_strerror, int errcode)
2060{
2061  const char *buf;
2062  buf = gai_strerror (errcode);
2063  if (buf != NULL)
2064    __mf_register ((void *) buf, strlen(buf)+1, __MF_TYPE_STATIC,
2065                   "gai_strerror() return");
2066  return buf;
2067}
2068#endif
2069
2070
2071#ifdef HAVE_GETMNTENT
2072WRAPPER2(struct mntent *, getmntent, FILE *filep)
2073{
2074  struct mntent *m;
2075  static struct mntent *last = NULL;
2076
2077  MF_VALIDATE_EXTENT (filep, sizeof (*filep), __MF_CHECK_WRITE,
2078    "getmntent stream");
2079#define UR(field) __mf_unregister(last->field, strlen (last->field)+1, __MF_TYPE_STATIC)
2080  if (last)
2081    {
2082      UR (mnt_fsname);
2083      UR (mnt_dir);
2084      UR (mnt_type);
2085      UR (mnt_opts);
2086      __mf_unregister (last, sizeof (*last), __MF_TYPE_STATIC);
2087    }
2088#undef UR
2089
2090  m = getmntent (filep);
2091  last = m;
2092
2093#define R(field) __mf_register(last->field, strlen (last->field)+1, __MF_TYPE_STATIC, "mntent " #field)
2094  if (m)
2095    {
2096      R (mnt_fsname);
2097      R (mnt_dir);
2098      R (mnt_type);
2099      R (mnt_opts);
2100      __mf_register (last, sizeof (*last), __MF_TYPE_STATIC, "getmntent result");
2101    }
2102#undef R
2103
2104  return m;
2105}
2106#endif
2107
2108
2109#ifdef HAVE_INET_NTOA
2110WRAPPER2(char *, inet_ntoa, struct in_addr in)
2111{
2112  static char *last_buf = NULL;
2113  char *buf;
2114  if (last_buf)
2115    __mf_unregister (last_buf, strlen (last_buf)+1, __MF_TYPE_STATIC);
2116  buf = inet_ntoa (in);
2117  last_buf = buf;
2118  if (buf)
2119    __mf_register (last_buf, strlen (last_buf)+1, __MF_TYPE_STATIC, "inet_ntoa result");
2120  return buf;
2121}
2122#endif
2123
2124
2125#ifdef HAVE_GETPROTOENT
2126WRAPPER2(struct protoent *, getprotoent, void)
2127{
2128  struct protoent *buf;
2129  buf = getprotoent ();
2130  if (buf != NULL)
2131    __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC, "getproto*() return");
2132  return buf;
2133}
2134#endif
2135
2136
2137#ifdef HAVE_GETPROTOBYNAME
2138WRAPPER2(struct protoent *, getprotobyname, const char *name)
2139{
2140  struct protoent *buf;
2141  MF_VALIDATE_EXTENT(name, strlen(name)+1, __MF_CHECK_READ,
2142                     "getprotobyname name");
2143  buf = getprotobyname (name);
2144  if (buf != NULL)
2145    __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
2146                   "getproto*() return");
2147  return buf;
2148}
2149#endif
2150
2151
2152#ifdef HAVE_GETPROTOBYNUMBER
2153WRAPPER2(struct protoent *, getprotobynumber, int port)
2154{
2155  struct protoent *buf;
2156  buf = getprotobynumber (port);
2157  if (buf != NULL)
2158    __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
2159                   "getproto*() return");
2160  return buf;
2161}
2162#endif
2163