OSDN Git Service

2005-03-17 Frank Ch. Eigler <fche@redhat.com>
[pf3gnuchains/gcc-fork.git] / libmudflap / mf-hooks2.c
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
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2, or (at your option) any later
11 version.
12
13 In addition to the permissions in the GNU General Public License, the
14 Free Software Foundation gives you unlimited permission to link the
15 compiled version of this file into combinations with other programs,
16 and to distribute those combinations without any restriction coming
17 from the use of this file.  (The General Public License restrictions
18 do apply in other respects; for example, they cover modification of
19 the file, and distribution when not linked into a combine
20 executable.)
21
22 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
23 WARRANTY; without even the implied warranty of MERCHANTABILITY or
24 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
25 for more details.
26
27 You should have received a copy of the GNU General Public License
28 along with GCC; see the file COPYING.  If not, write to the Free
29 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
30 02111-1307, 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
121 static 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
134 WRAPPER2(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
143 WRAPPER2(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
152 WRAPPER2(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
160 WRAPPER2(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
169 WRAPPER2(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
178 WRAPPER2(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
187 WRAPPER2(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
202 WRAPPER2(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
213 WRAPPER2(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
227 WRAPPER2(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
262 WRAPPER2(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
275 WRAPPER2(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
288 WRAPPER2(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
301 WRAPPER2(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
314 WRAPPER2(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
337 WRAPPER2(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
362 WRAPPER2(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
372 WRAPPER2(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
382 WRAPPER2(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
396 WRAPPER2(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
408 WRAPPER2(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
417 WRAPPER2(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
426 WRAPPER2(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
435 WRAPPER2(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
445 WRAPPER2(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
454 WRAPPER2(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
463 WRAPPER2(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
477 WRAPPER2(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
493 WRAPPER2(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
510 WRAPPER2(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
526 WRAPPER2(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 #undef  MF_REGISTER_fopen
548 #define MF_RESULT_SIZE_fopen            (sizeof (FILE))
549 #undef  MF_REGISTER_opendir
550 #define MF_RESULT_SIZE_opendir          0       /* (sizeof (DIR)) */
551 #undef  MF_REGISTER_readdir
552 #define MF_REGISTER_gethostbyname       __MF_TYPE_STATIC
553 #undef  MF_REGISTER_gethostbyname_items
554 #undef  MF_REGISTER_dlopen
555 #undef  MF_REGISTER_dlerror
556 #undef  MF_REGISTER_dlsym
557 #define MF_REGISTER_shmat               __MF_TYPE_GUESS
558
559
560 #include <time.h>
561 WRAPPER2(time_t, time, time_t *timep)
562 {
563   TRACE ("%s\n", __PRETTY_FUNCTION__);
564   if (NULL != timep)
565     MF_VALIDATE_EXTENT (timep, sizeof (*timep), __MF_CHECK_WRITE,
566       "time timep");
567   return time (timep);
568 }
569
570
571 WRAPPER2(char *, strerror, int errnum)
572 {
573   char *p;
574   static char * last_strerror = NULL;
575
576   TRACE ("%s\n", __PRETTY_FUNCTION__);
577   p = strerror (errnum);
578   if (last_strerror != NULL)
579     __mf_unregister (last_strerror, 0, __MF_TYPE_STATIC);
580   if (NULL != p)
581     __mf_register (p, strlen (p) + 1, __MF_TYPE_STATIC, "strerror result");
582   last_strerror = p;
583   return p;
584 }
585
586
587
588 /* An auxiliary data structure for tracking the hand-made stdio
589    buffers we generate during the fopen/fopen64 hooks.  In a civilized
590    language, this would be a simple dynamically sized FILE*->char*
591    lookup table, but this is C and we get to do it by hand.  */
592 struct mf_filebuffer
593 {
594   FILE *file;
595   char *buffer;
596   struct mf_filebuffer *next;
597 };
598 static struct mf_filebuffer *mf_filebuffers = NULL;
599
600 static void
601 mkbuffer (FILE *f)
602 {
603   /* Reset any buffer automatically provided by libc, since this may
604      have been done via mechanisms that libmudflap couldn't
605      intercept.  */
606   int rc;
607   size_t bufsize = BUFSIZ;
608   int bufmode;
609   char *buffer = malloc (bufsize);
610   struct mf_filebuffer *b = malloc (sizeof (struct mf_filebuffer));
611   assert ((buffer != NULL) && (b != NULL));
612
613   /* Link it into list.  */
614   b->file = f;
615   b->buffer = buffer;
616   b->next = mf_filebuffers;
617   mf_filebuffers = b;
618
619   /* Determine how the file is supposed to be buffered at the moment.  */
620   bufmode = fileno (f) == 2 ? _IONBF : (isatty (fileno (f)) ? _IOLBF : _IOFBF);
621
622   rc = setvbuf (f, buffer, bufmode, bufsize);
623   assert (rc == 0);
624 }
625
626 static void
627 unmkbuffer (FILE *f)
628 {
629   struct mf_filebuffer *b = mf_filebuffers;
630   struct mf_filebuffer **pb = & mf_filebuffers;
631   while (b != NULL)
632     {
633       if (b->file == f)
634         {
635           *pb = b->next;
636           free (b->buffer);
637           free (b);
638           return;
639         }
640       pb = & b->next;
641       b = b->next;
642     }
643 }
644
645
646
647 WRAPPER2(FILE *, fopen, const char *path, const char *mode)
648 {
649   size_t n;
650   FILE *p;
651   TRACE ("%s\n", __PRETTY_FUNCTION__);
652
653   n = strlen (path);
654   MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "fopen path");
655
656   n = strlen (mode);
657   MF_VALIDATE_EXTENT (mode, CLAMPADD(n, 1), __MF_CHECK_READ, "fopen mode");
658
659   p = fopen (path, mode);
660   if (NULL != p) {
661 #ifdef MF_REGISTER_fopen
662     __mf_register (p, sizeof (*p), MF_REGISTER_fopen, "fopen result");
663 #endif
664     MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_WRITE, "fopen result");
665
666     mkbuffer (p);
667   }
668
669   return p;
670 }
671
672
673 WRAPPER2(int, setvbuf, FILE *stream, char *buf, int mode, size_t size)
674 {
675   int rc = 0;
676   TRACE ("%s\n", __PRETTY_FUNCTION__);
677
678   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE, "setvbuf stream");
679
680   unmkbuffer (stream);
681
682   if (buf != NULL)
683     MF_VALIDATE_EXTENT (buf, size, __MF_CHECK_WRITE, "setvbuf buffer");
684
685   /* Override the user only if it's an auto-allocated buffer request.  Otherwise
686      assume that the supplied buffer is already known to libmudflap.  */
687   if ((buf == NULL) && ((mode == _IOFBF) || (mode == _IOLBF)))
688     mkbuffer (stream);
689   else
690     rc = setvbuf (stream, buf, mode, size);
691
692   return rc;
693 }
694
695
696 #ifdef HAVE_SETBUF
697 WRAPPER2(int, setbuf, FILE* stream, char *buf)
698 {
699   return __mfwrap_setvbuf (stream, buf, buf ? _IOFBF : _IONBF, BUFSIZ);
700 }
701 #endif
702
703 #ifdef HAVE_SETBUFFER
704 WRAPPER2(int, setbuffer, FILE* stream, char *buf, size_t sz)
705 {
706   return __mfwrap_setvbuf (stream, buf, buf ? _IOFBF : _IONBF, sz);
707 }
708 #endif
709
710 #ifdef HAVE_SETLINEBUF
711 WRAPPER2(int, setlinebuf, FILE* stream)
712 {
713   return __mfwrap_setvbuf(stream, NULL, _IOLBF, 0);
714 }
715 #endif
716
717
718
719 WRAPPER2(FILE *, fdopen, int fd, const char *mode)
720 {
721   size_t n;
722   FILE *p;
723   TRACE ("%s\n", __PRETTY_FUNCTION__);
724
725   n = strlen (mode);
726   MF_VALIDATE_EXTENT (mode, CLAMPADD(n, 1), __MF_CHECK_READ, "fdopen mode");
727
728   p = fdopen (fd, mode);
729   if (NULL != p) {
730 #ifdef MF_REGISTER_fopen
731     __mf_register (p, sizeof (*p), MF_REGISTER_fopen, "fdopen result");
732 #endif
733     MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_WRITE, "fdopen result");
734
735     mkbuffer (p);
736   }
737
738   return p;
739 }
740
741
742 WRAPPER2(FILE *, freopen, const char *path, const char *mode, FILE *s)
743 {
744   size_t n;
745   FILE *p;
746   TRACE ("%s\n", __PRETTY_FUNCTION__);
747
748   n = strlen (path);
749   MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "freopen path");
750
751   MF_VALIDATE_EXTENT (s, (sizeof (*s)), __MF_CHECK_WRITE, "freopen stream");
752   unmkbuffer (s);
753
754   n = strlen (mode);
755   MF_VALIDATE_EXTENT (mode, CLAMPADD(n, 1), __MF_CHECK_READ, "freopen mode");
756
757   p = freopen (path, mode, s);
758   if (NULL != p) {
759 #ifdef MF_REGISTER_fopen
760     __mf_register (p, sizeof (*p), MF_REGISTER_fopen, "freopen result");
761 #endif
762     MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_WRITE, "freopen result");
763
764     mkbuffer (p);
765   }
766
767   return p;
768 }
769
770
771 #ifdef HAVE_FOPEN64
772 WRAPPER2(FILE *, fopen64, const char *path, const char *mode)
773 {
774   size_t n;
775   FILE *p;
776   TRACE ("%s\n", __PRETTY_FUNCTION__);
777
778   n = strlen (path);
779   MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "fopen64 path");
780
781   n = strlen (mode);
782   MF_VALIDATE_EXTENT (mode, CLAMPADD(n, 1), __MF_CHECK_READ, "fopen64 mode");
783
784   p = fopen64 (path, mode);
785   if (NULL != p) {
786 #ifdef MF_REGISTER_fopen
787     __mf_register (p, sizeof (*p), MF_REGISTER_fopen, "fopen64 result");
788 #endif
789     MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_WRITE, "fopen64 result");
790
791     mkbuffer (p);
792   }
793
794   return p;
795 }
796 #endif
797
798
799 #ifdef HAVE_FREOPEN64
800 WRAPPER2(FILE *, freopen64, const char *path, const char *mode, FILE *s)
801 {
802   size_t n;
803   FILE *p;
804   TRACE ("%s\n", __PRETTY_FUNCTION__);
805
806   n = strlen (path);
807   MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "freopen64 path");
808
809   MF_VALIDATE_EXTENT (s, (sizeof (*s)), __MF_CHECK_WRITE, "freopen64 stream");
810   unmkbuffer (s);
811
812   n = strlen (mode);
813   MF_VALIDATE_EXTENT (mode, CLAMPADD(n, 1), __MF_CHECK_READ, "freopen64 mode");
814
815   p = freopen (path, mode, s);
816   if (NULL != p) {
817 #ifdef MF_REGISTER_fopen
818     __mf_register (p, sizeof (*p), MF_REGISTER_fopen, "freopen64 result");
819 #endif
820     MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_WRITE, "freopen64 result");
821
822     mkbuffer (p);
823   }
824
825   return p;
826 }
827 #endif
828
829
830 WRAPPER2(int, fclose, FILE *stream)
831 {
832   int resp;
833   TRACE ("%s\n", __PRETTY_FUNCTION__);
834   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
835     "fclose stream");
836   resp = fclose (stream);
837 #ifdef MF_REGISTER_fopen
838   __mf_unregister (stream, sizeof (*stream), MF_REGISTER_fopen);
839 #endif
840   unmkbuffer (stream);
841
842   return resp;
843 }
844
845
846 WRAPPER2(size_t, fread, void *ptr, size_t size, size_t nmemb, FILE *stream)
847 {
848   TRACE ("%s\n", __PRETTY_FUNCTION__);
849   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
850     "fread stream");
851   MF_VALIDATE_EXTENT (ptr, size * nmemb, __MF_CHECK_WRITE, "fread buffer");
852   return fread (ptr, size, nmemb, stream);
853 }
854
855
856 WRAPPER2(size_t, fwrite, const void *ptr, size_t size, size_t nmemb,
857         FILE *stream)
858 {
859   TRACE ("%s\n", __PRETTY_FUNCTION__);
860   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
861     "fwrite stream");
862   MF_VALIDATE_EXTENT (ptr, size * nmemb, __MF_CHECK_READ, "fwrite buffer");
863   return fwrite (ptr, size, nmemb, stream);
864 }
865
866
867 WRAPPER2(int, fgetc, FILE *stream)
868 {
869   TRACE ("%s\n", __PRETTY_FUNCTION__);
870   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
871     "fgetc stream");
872   return fgetc (stream);
873 }
874
875
876 WRAPPER2(char *, fgets, char *s, int size, FILE *stream)
877 {
878   TRACE ("%s\n", __PRETTY_FUNCTION__);
879   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
880     "fgets stream");
881   MF_VALIDATE_EXTENT (s, size, __MF_CHECK_WRITE, "fgets buffer");
882   return fgets (s, size, stream);
883 }
884
885
886 WRAPPER2(int, getc, FILE *stream)
887 {
888   TRACE ("%s\n", __PRETTY_FUNCTION__);
889   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
890     "getc stream");
891   return getc (stream);
892 }
893
894
895 WRAPPER2(char *, gets, char *s)
896 {
897   TRACE ("%s\n", __PRETTY_FUNCTION__);
898   MF_VALIDATE_EXTENT (s, 1, __MF_CHECK_WRITE, "gets buffer");
899   /* Avoid link-time warning... */
900   s = fgets (s, INT_MAX, stdin);
901   if (NULL != s) {      /* better late than never */
902     size_t n = strlen (s);
903     MF_VALIDATE_EXTENT (s, CLAMPADD(n, 1), __MF_CHECK_WRITE, "gets buffer");
904   }
905   return s;
906 }
907
908
909 WRAPPER2(int, ungetc, int c, FILE *stream)
910 {
911   TRACE ("%s\n", __PRETTY_FUNCTION__);
912   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
913      "ungetc stream");
914   return ungetc (c, stream);
915 }
916
917
918 WRAPPER2(int, fputc, int c, FILE *stream)
919 {
920   TRACE ("%s\n", __PRETTY_FUNCTION__);
921   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
922     "fputc stream");
923   return fputc (c, stream);
924 }
925
926
927 WRAPPER2(int, fputs, const char *s, FILE *stream)
928 {
929   size_t n;
930   TRACE ("%s\n", __PRETTY_FUNCTION__);
931   n = strlen (s);
932   MF_VALIDATE_EXTENT (s, CLAMPADD(n, 1), __MF_CHECK_READ, "fputs buffer");
933   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
934     "fputs stream");
935   return fputs (s, stream);
936 }
937
938
939 WRAPPER2(int, putc, int c, FILE *stream)
940 {
941   TRACE ("%s\n", __PRETTY_FUNCTION__);
942   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
943     "putc stream");
944   return putc (c, stream);
945 }
946
947
948 WRAPPER2(int, puts, const char *s)
949 {
950   size_t n;
951   TRACE ("%s\n", __PRETTY_FUNCTION__);
952   n = strlen (s);
953   MF_VALIDATE_EXTENT (s, CLAMPADD(n, 1), __MF_CHECK_READ, "puts buffer");
954   return puts (s);
955 }
956
957
958 WRAPPER2(void, clearerr, FILE *stream)
959 {
960   TRACE ("%s\n", __PRETTY_FUNCTION__);
961   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
962     "clearerr stream");
963   clearerr (stream);
964 }
965
966
967 WRAPPER2(int, feof, FILE *stream)
968 {
969   TRACE ("%s\n", __PRETTY_FUNCTION__);
970   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
971     "feof stream");
972   return feof (stream);
973 }
974
975
976 WRAPPER2(int, ferror, FILE *stream)
977 {
978   TRACE ("%s\n", __PRETTY_FUNCTION__);
979   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
980     "ferror stream");
981   return ferror (stream);
982 }
983
984
985 WRAPPER2(int, fileno, FILE *stream)
986 {
987   TRACE ("%s\n", __PRETTY_FUNCTION__);
988   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
989     "fileno stream");
990   return fileno (stream);
991 }
992
993
994 WRAPPER2(int, printf, const char *format, ...)
995 {
996   size_t n;
997   va_list ap;
998   int result;
999   TRACE ("%s\n", __PRETTY_FUNCTION__);
1000   n = strlen (format);
1001   MF_VALIDATE_EXTENT (format, CLAMPADD(n, 1), __MF_CHECK_READ,
1002     "printf format");
1003   va_start (ap, format);
1004   result = vprintf (format, ap);
1005   va_end (ap);
1006   return result;
1007 }
1008
1009
1010 WRAPPER2(int, fprintf, FILE *stream, const char *format, ...)
1011 {
1012   size_t n;
1013   va_list ap;
1014   int result;
1015   TRACE ("%s\n", __PRETTY_FUNCTION__);
1016   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
1017     "fprintf stream");
1018   n = strlen (format);
1019   MF_VALIDATE_EXTENT (format, CLAMPADD(n, 1), __MF_CHECK_READ,
1020     "fprintf format");
1021   va_start (ap, format);
1022   result = vfprintf (stream, format, ap);
1023   va_end (ap);
1024   return result;
1025 }
1026
1027
1028 WRAPPER2(int, sprintf, char *str, const char *format, ...)
1029 {
1030   size_t n;
1031   va_list ap;
1032   int result;
1033   TRACE ("%s\n", __PRETTY_FUNCTION__);
1034   MF_VALIDATE_EXTENT (str, 1, __MF_CHECK_WRITE, "sprintf str");
1035   n = strlen (format);
1036   MF_VALIDATE_EXTENT (format, CLAMPADD(n, 1), __MF_CHECK_READ,
1037     "sprintf format");
1038   va_start (ap, format);
1039   result = vsprintf (str, format, ap);
1040   va_end (ap);
1041   n = strlen (str);
1042   MF_VALIDATE_EXTENT (str, CLAMPADD(n, 1), __MF_CHECK_WRITE, "sprintf str");
1043   return result;
1044 }
1045
1046
1047 WRAPPER2(int, snprintf, char *str, size_t size, const char *format, ...)
1048 {
1049   size_t n;
1050   va_list ap;
1051   int result;
1052   TRACE ("%s\n", __PRETTY_FUNCTION__);
1053   MF_VALIDATE_EXTENT (str, size, __MF_CHECK_WRITE, "snprintf str");
1054   n = strlen (format);
1055   MF_VALIDATE_EXTENT (format, CLAMPADD(n, 1), __MF_CHECK_READ,
1056     "snprintf format");
1057   va_start (ap, format);
1058   result = vsnprintf (str, size, format, ap);
1059   va_end (ap);
1060   return result;
1061 }
1062
1063
1064 WRAPPER2(int, vprintf,  const char *format, va_list ap)
1065 {
1066   size_t n;
1067   TRACE ("%s\n", __PRETTY_FUNCTION__);
1068   n = strlen (format);
1069   MF_VALIDATE_EXTENT (format, CLAMPADD(n, 1), __MF_CHECK_READ,
1070     "vprintf format");
1071   return vprintf (format, ap);
1072 }
1073
1074
1075 WRAPPER2(int, vfprintf, FILE *stream, const char *format, va_list ap)
1076 {
1077   size_t n;
1078   TRACE ("%s\n", __PRETTY_FUNCTION__);
1079   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
1080     "vfprintf stream");
1081   n = strlen (format);
1082   MF_VALIDATE_EXTENT (format, CLAMPADD(n, 1), __MF_CHECK_READ,
1083     "vfprintf format");
1084   return vfprintf (stream, format, ap);
1085 }
1086
1087
1088 WRAPPER2(int, vsprintf, char *str, const char *format, va_list ap)
1089 {
1090   size_t n;
1091   int result;
1092   TRACE ("%s\n", __PRETTY_FUNCTION__);
1093   MF_VALIDATE_EXTENT (str, 1, __MF_CHECK_WRITE, "vsprintf str");
1094   n = strlen (format);
1095   MF_VALIDATE_EXTENT (format, CLAMPADD(n, 1), __MF_CHECK_READ,
1096     "vsprintf format");
1097   result = vsprintf (str, format, ap);
1098   n = strlen (str);
1099   MF_VALIDATE_EXTENT (str, CLAMPADD(n, 1), __MF_CHECK_WRITE, "vsprintf str");
1100   return result;
1101 }
1102
1103
1104 WRAPPER2(int, vsnprintf, char *str, size_t size, const char *format,
1105         va_list ap)
1106 {
1107   size_t n;
1108   TRACE ("%s\n", __PRETTY_FUNCTION__);
1109   MF_VALIDATE_EXTENT (str, size, __MF_CHECK_WRITE, "vsnprintf str");
1110   n = strlen (format);
1111   MF_VALIDATE_EXTENT (format, CLAMPADD(n, 1), __MF_CHECK_READ,
1112     "vsnprintf format");
1113   return vsnprintf (str, size, format, ap);
1114 }
1115
1116
1117 WRAPPER2(int , access, const char *path, int mode)
1118 {
1119   size_t n;
1120   TRACE ("%s\n", __PRETTY_FUNCTION__);
1121   n = strlen (path);
1122   MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "access path");
1123   return access (path, mode);
1124 }
1125
1126
1127 WRAPPER2(int , remove, const char *path)
1128 {
1129   size_t n;
1130   TRACE ("%s\n", __PRETTY_FUNCTION__);
1131   n = strlen (path);
1132   MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "remove path");
1133   return remove (path);
1134 }
1135
1136
1137 WRAPPER2(int, fflush, FILE *stream)
1138 {
1139   TRACE ("%s\n", __PRETTY_FUNCTION__);
1140   if (stream != NULL)
1141     MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
1142                         "fflush stream");
1143   return fflush (stream);
1144 }
1145
1146
1147 WRAPPER2(int, fseek, FILE *stream, long offset, int whence)
1148 {
1149   TRACE ("%s\n", __PRETTY_FUNCTION__);
1150   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
1151     "fseek stream");
1152   return fseek (stream, offset, whence);
1153 }
1154
1155
1156 #ifdef HAVE_FSEEKO64
1157 WRAPPER2(int, fseeko64, FILE *stream, off64_t offset, int whence)
1158 {
1159   TRACE ("%s\n", __PRETTY_FUNCTION__);
1160   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
1161     "fseeko64 stream");
1162   return fseeko64 (stream, offset, whence);
1163 }
1164 #endif
1165
1166
1167 WRAPPER2(long, ftell, FILE *stream)
1168 {
1169   TRACE ("%s\n", __PRETTY_FUNCTION__);
1170   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
1171     "ftell stream");
1172   return ftell (stream);
1173 }
1174
1175
1176 #ifdef HAVE_FTELLO64
1177 WRAPPER2(off64_t, ftello64, FILE *stream)
1178 {
1179   TRACE ("%s\n", __PRETTY_FUNCTION__);
1180   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
1181     "ftello64 stream");
1182   return ftello64 (stream);
1183 }
1184 #endif
1185
1186
1187 WRAPPER2(void, rewind, FILE *stream)
1188 {
1189   TRACE ("%s\n", __PRETTY_FUNCTION__);
1190   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
1191     "rewind stream");
1192   rewind (stream);
1193 }
1194
1195
1196 WRAPPER2(int, fgetpos, FILE *stream, fpos_t *pos)
1197 {
1198   TRACE ("%s\n", __PRETTY_FUNCTION__);
1199   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
1200     "fgetpos stream");
1201   MF_VALIDATE_EXTENT (pos, sizeof (*pos), __MF_CHECK_WRITE, "fgetpos pos");
1202   return fgetpos (stream, pos);
1203 }
1204
1205
1206 WRAPPER2(int, fsetpos, FILE *stream, fpos_t *pos)
1207 {
1208   TRACE ("%s\n", __PRETTY_FUNCTION__);
1209   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
1210     "fsetpos stream");
1211   MF_VALIDATE_EXTENT (pos, sizeof (*pos), __MF_CHECK_READ, "fsetpos pos");
1212   return fsetpos (stream, pos);
1213 }
1214
1215
1216 WRAPPER2(int , stat, const char *path, struct stat *buf)
1217 {
1218   size_t n;
1219   TRACE ("%s\n", __PRETTY_FUNCTION__);
1220   n = strlen (path);
1221   MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "stat path");
1222   MF_VALIDATE_EXTENT (buf, sizeof (*buf), __MF_CHECK_READ, "stat buf");
1223   return stat (path, buf);
1224 }
1225
1226
1227 #ifdef HAVE_STAT64
1228 WRAPPER2(int , stat64, const char *path, struct stat64 *buf)
1229 {
1230   size_t n;
1231   TRACE ("%s\n", __PRETTY_FUNCTION__);
1232   n = strlen (path);
1233   MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "stat64 path");
1234   MF_VALIDATE_EXTENT (buf, sizeof (*buf), __MF_CHECK_READ, "stat64 buf");
1235   return stat64 (path, buf);
1236 }
1237 #endif
1238
1239
1240 WRAPPER2(int , fstat, int filedes, struct stat *buf)
1241 {
1242   TRACE ("%s\n", __PRETTY_FUNCTION__);
1243   MF_VALIDATE_EXTENT (buf, sizeof (*buf), __MF_CHECK_READ, "fstat buf");
1244   return fstat (filedes, buf);
1245 }
1246
1247
1248 WRAPPER2(int , lstat, const char *path, struct stat *buf)
1249 {
1250   size_t n;
1251   TRACE ("%s\n", __PRETTY_FUNCTION__);
1252   n = strlen (path);
1253   MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "lstat path");
1254   MF_VALIDATE_EXTENT (buf, sizeof (*buf), __MF_CHECK_READ, "lstat buf");
1255   return lstat (path, buf);
1256 }
1257
1258
1259 WRAPPER2(int , mkfifo, const char *path, mode_t mode)
1260 {
1261   size_t n;
1262   TRACE ("%s\n", __PRETTY_FUNCTION__);
1263   n = strlen (path);
1264   MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "mkfifo path");
1265   return mkfifo (path, mode);
1266 }
1267
1268
1269 #ifdef HAVE_DIRENT_H
1270 WRAPPER2(DIR *, opendir, const char *path)
1271 {
1272   DIR *p;
1273   size_t n;
1274   TRACE ("%s\n", __PRETTY_FUNCTION__);
1275   n = strlen (path);
1276   MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "opendir path");
1277
1278   p = opendir (path);
1279   if (NULL != p) {
1280 #ifdef MF_REGISTER_opendir
1281     __mf_register (p, MF_RESULT_SIZE_opendir, MF_REGISTER_opendir,
1282       "opendir result");
1283 #endif
1284     MF_VALIDATE_EXTENT (p, MF_RESULT_SIZE_opendir, __MF_CHECK_WRITE,
1285       "opendir result");
1286   }
1287   return p;
1288 }
1289
1290
1291 WRAPPER2(int, closedir, DIR *dir)
1292 {
1293   TRACE ("%s\n", __PRETTY_FUNCTION__);
1294   MF_VALIDATE_EXTENT (dir, 0, __MF_CHECK_WRITE, "closedir dir");
1295 #ifdef MF_REGISTER_opendir
1296   __mf_unregister (dir, MF_RESULT_SIZE_opendir, MF_REGISTER_opendir);
1297 #endif
1298   return closedir (dir);
1299 }
1300
1301
1302 WRAPPER2(struct dirent *, readdir, DIR *dir)
1303 {
1304   struct dirent *p;
1305   TRACE ("%s\n", __PRETTY_FUNCTION__);
1306   MF_VALIDATE_EXTENT (dir, 0, __MF_CHECK_READ, "readdir dir");
1307   p = readdir (dir);
1308   if (NULL != p) {
1309 #ifdef MF_REGISTER_readdir
1310     __mf_register (p, sizeof (*p), MF_REGISTER_readdir, "readdir result");
1311 #endif
1312     MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_WRITE, "readdir result");
1313   }
1314   return p;
1315 }
1316 #endif
1317
1318
1319 #ifdef HAVE_SYS_SOCKET_H
1320
1321 WRAPPER2(int, recv, int s, void *buf, size_t len, int flags)
1322 {
1323   TRACE ("%s\n", __PRETTY_FUNCTION__);
1324   MF_VALIDATE_EXTENT (buf, len, __MF_CHECK_WRITE, "recv buf");
1325   return recv (s, buf, len, flags);
1326 }
1327
1328
1329 WRAPPER2(int, recvfrom, int s, void *buf, size_t len, int flags,
1330                 struct sockaddr *from, socklen_t *fromlen)
1331 {
1332   TRACE ("%s\n", __PRETTY_FUNCTION__);
1333   MF_VALIDATE_EXTENT (buf, len, __MF_CHECK_WRITE, "recvfrom buf");
1334   MF_VALIDATE_EXTENT (from, (size_t)*fromlen, __MF_CHECK_WRITE,
1335     "recvfrom from");
1336   return recvfrom (s, buf, len, flags, from, fromlen);
1337 }
1338
1339
1340 WRAPPER2(int, recvmsg, int s, struct msghdr *msg, int flags)
1341 {
1342   TRACE ("%s\n", __PRETTY_FUNCTION__);
1343   MF_VALIDATE_EXTENT (msg, sizeof (*msg), __MF_CHECK_WRITE, "recvmsg msg");
1344   return recvmsg (s, msg, flags);
1345 }
1346
1347
1348 WRAPPER2(int, send, int s, const void *msg, size_t len, int flags)
1349 {
1350   TRACE ("%s\n", __PRETTY_FUNCTION__);
1351   MF_VALIDATE_EXTENT (msg, len, __MF_CHECK_READ, "send msg");
1352   return send (s, msg, len, flags);
1353 }
1354
1355
1356 WRAPPER2(int, sendto, int s, const void *msg, size_t len, int flags,
1357                 const struct sockaddr *to, socklen_t tolen)
1358 {
1359   TRACE ("%s\n", __PRETTY_FUNCTION__);
1360   MF_VALIDATE_EXTENT (msg, len, __MF_CHECK_READ, "sendto msg");
1361   MF_VALIDATE_EXTENT (to, (size_t)tolen, __MF_CHECK_WRITE, "sendto to");
1362   return sendto (s, msg, len, flags, to, tolen);
1363 }
1364
1365
1366 WRAPPER2(int, sendmsg, int s, const void *msg, int flags)
1367 {
1368   TRACE ("%s\n", __PRETTY_FUNCTION__);
1369   MF_VALIDATE_EXTENT (msg, sizeof (*msg), __MF_CHECK_READ, "sendmsg msg");
1370   return sendmsg (s, msg, flags);
1371 }
1372
1373
1374 WRAPPER2(int, setsockopt, int s, int level, int optname, const void *optval,
1375         socklen_t optlen)
1376 {
1377   TRACE ("%s\n", __PRETTY_FUNCTION__);
1378   MF_VALIDATE_EXTENT (optval, (size_t)optlen, __MF_CHECK_READ,
1379     "setsockopt optval");
1380   return setsockopt (s, level, optname, optval, optlen);
1381 }
1382
1383
1384 WRAPPER2(int, getsockopt, int s, int level, int optname, void *optval,
1385                 socklen_t *optlen)
1386 {
1387   TRACE ("%s\n", __PRETTY_FUNCTION__);
1388   MF_VALIDATE_EXTENT (optval, (size_t)*optlen, __MF_CHECK_WRITE,
1389     "getsockopt optval");
1390   return getsockopt (s, level, optname, optval, optlen);
1391 }
1392
1393
1394 WRAPPER2(int, accept, int s, struct  sockaddr *addr, socklen_t *addrlen)
1395 {
1396   TRACE ("%s\n", __PRETTY_FUNCTION__);
1397   MF_VALIDATE_EXTENT (addr, (size_t)*addrlen, __MF_CHECK_WRITE, "accept addr");
1398   return accept (s, addr, addrlen);
1399 }
1400
1401
1402 WRAPPER2(int, bind, int sockfd, struct  sockaddr *addr, socklen_t addrlen)
1403 {
1404   TRACE ("%s\n", __PRETTY_FUNCTION__);
1405   MF_VALIDATE_EXTENT (addr, (size_t)addrlen, __MF_CHECK_WRITE, "bind addr");
1406   return bind (sockfd, addr, addrlen);
1407 }
1408
1409
1410 WRAPPER2(int, connect, int sockfd, const struct sockaddr  *addr,
1411         socklen_t addrlen)
1412 {
1413   TRACE ("%s\n", __PRETTY_FUNCTION__);
1414   MF_VALIDATE_EXTENT (addr, (size_t)addrlen, __MF_CHECK_READ,
1415     "connect addr");
1416   return connect (sockfd, addr, addrlen);
1417 }
1418
1419 #endif /* HAVE_SYS_SOCKET_H */
1420
1421
1422 WRAPPER2(int, gethostname, char *name, size_t len)
1423 {
1424   TRACE ("%s\n", __PRETTY_FUNCTION__);
1425   MF_VALIDATE_EXTENT (name, len, __MF_CHECK_WRITE, "gethostname name");
1426   return gethostname (name, len);
1427 }
1428
1429
1430 #ifdef HAVE_SETHOSTNAME
1431 WRAPPER2(int, sethostname, const char *name, size_t len)
1432 {
1433   TRACE ("%s\n", __PRETTY_FUNCTION__);
1434   MF_VALIDATE_EXTENT (name, len, __MF_CHECK_READ, "sethostname name");
1435   return sethostname (name, len);
1436 }
1437 #endif
1438
1439
1440 #ifdef HAVE_NETDB_H
1441
1442 WRAPPER2(struct hostent *, gethostbyname, const char *name)
1443 {
1444   struct hostent *p;
1445   char **ss;
1446   char *s;
1447   size_t n;
1448   int nreg;
1449   TRACE ("%s\n", __PRETTY_FUNCTION__);
1450   n = strlen (name);
1451   MF_VALIDATE_EXTENT (name, CLAMPADD(n, 1), __MF_CHECK_READ,
1452     "gethostbyname name");
1453   p = gethostbyname (name);
1454   if (NULL != p) {
1455 #ifdef MF_REGISTER_gethostbyname
1456     __mf_register (p, sizeof (*p), MF_REGISTER_gethostbyname,
1457       "gethostbyname result");
1458 #endif
1459     MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_WRITE,
1460       "gethostbyname result");
1461     if (NULL != (s = p->h_name)) {
1462       n = strlen (s);
1463       n = CLAMPADD(n, 1);
1464 #ifdef MF_REGISTER_gethostbyname_items
1465       __mf_register (s, n, MF_REGISTER_gethostbyname_items,
1466         "gethostbyname result->h_name");
1467 #endif
1468       MF_VALIDATE_EXTENT (s, n, __MF_CHECK_WRITE,
1469         "gethostbyname result->h_name");
1470     }
1471
1472     if (NULL != (ss = p->h_aliases)) {
1473       for (nreg = 1;; ++nreg) {
1474         s = *ss++;
1475         if (NULL == s)
1476           break;
1477         n = strlen (s);
1478         n = CLAMPADD(n, 1);
1479 #ifdef MF_REGISTER_gethostbyname_items
1480         __mf_register (s, n, MF_REGISTER_gethostbyname_items,
1481           "gethostbyname result->h_aliases[]");
1482 #endif
1483         MF_VALIDATE_EXTENT (s, n, __MF_CHECK_WRITE,
1484           "gethostbyname result->h_aliases[]");
1485       }
1486       nreg *= sizeof (*p->h_aliases);
1487 #ifdef MF_REGISTER_gethostbyname_items
1488       __mf_register (p->h_aliases, nreg, MF_REGISTER_gethostbyname_items,
1489         "gethostbyname result->h_aliases");
1490 #endif
1491       MF_VALIDATE_EXTENT (p->h_aliases, nreg, __MF_CHECK_WRITE,
1492         "gethostbyname result->h_aliases");
1493     }
1494
1495     if (NULL != (ss = p->h_addr_list)) {
1496       for (nreg = 1;; ++nreg) {
1497         s = *ss++;
1498         if (NULL == s)
1499           break;
1500 #ifdef MF_REGISTER_gethostbyname_items
1501         __mf_register (s, p->h_length, MF_REGISTER_gethostbyname_items,
1502           "gethostbyname result->h_addr_list[]");
1503 #endif
1504         MF_VALIDATE_EXTENT (s, p->h_length, __MF_CHECK_WRITE,
1505           "gethostbyname result->h_addr_list[]");
1506       }
1507       nreg *= sizeof (*p->h_addr_list);
1508 #ifdef MF_REGISTER_gethostbyname_items
1509       __mf_register (p->h_addr_list, nreg, MF_REGISTER_gethostbyname_items,
1510         "gethostbyname result->h_addr_list");
1511 #endif
1512       MF_VALIDATE_EXTENT (p->h_addr_list, nreg, __MF_CHECK_WRITE,
1513         "gethostbyname result->h_addr_list");
1514     }
1515   }
1516   return p;
1517 }
1518
1519 #endif /* HAVE_NETDB_H */
1520
1521
1522 #ifdef HAVE_SYS_WAIT_H
1523
1524 WRAPPER2(pid_t, wait, int *status)
1525 {
1526   TRACE ("%s\n", __PRETTY_FUNCTION__);
1527   if (NULL != status)
1528     MF_VALIDATE_EXTENT (status, sizeof (*status), __MF_CHECK_WRITE,
1529       "wait status");
1530   return wait (status);
1531 }
1532
1533
1534 WRAPPER2(pid_t, waitpid, pid_t pid, int *status, int options)
1535 {
1536   TRACE ("%s\n", __PRETTY_FUNCTION__);
1537   if (NULL != status)
1538     MF_VALIDATE_EXTENT (status, sizeof (*status), __MF_CHECK_WRITE,
1539       "waitpid status");
1540   return waitpid (pid, status, options);
1541 }
1542
1543 #endif /* HAVE_SYS_WAIT_H */
1544
1545
1546 WRAPPER2(FILE *, popen, const char *command, const char *mode)
1547 {
1548   size_t n;
1549   FILE *p;
1550   TRACE ("%s\n", __PRETTY_FUNCTION__);
1551
1552   n = strlen (command);
1553   MF_VALIDATE_EXTENT (command, CLAMPADD(n, 1), __MF_CHECK_READ, "popen path");
1554
1555   n = strlen (mode);
1556   MF_VALIDATE_EXTENT (mode, CLAMPADD(n, 1), __MF_CHECK_READ, "popen mode");
1557
1558   p = popen (command, mode);
1559   if (NULL != p) {
1560 #ifdef MF_REGISTER_fopen
1561     __mf_register (p, sizeof (*p), MF_REGISTER_fopen, "popen result");
1562 #endif
1563     MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_WRITE, "popen result");
1564   }
1565   return p;
1566 }
1567
1568
1569 WRAPPER2(int, pclose, FILE *stream)
1570 {
1571   int resp;
1572   TRACE ("%s\n", __PRETTY_FUNCTION__);
1573   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
1574     "pclose stream");
1575   resp = pclose (stream);
1576 #ifdef MF_REGISTER_fopen
1577   __mf_unregister (stream, sizeof (*stream), MF_REGISTER_fopen);
1578 #endif
1579   return resp;
1580 }
1581
1582
1583 WRAPPER2(int, execve, const char *path, char *const argv [],
1584         char *const envp[])
1585 {
1586   size_t n;
1587   char *const *p;
1588   const char *s;
1589   TRACE ("%s\n", __PRETTY_FUNCTION__);
1590
1591   n = strlen (path);
1592   MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "execve path");
1593
1594   for (p = argv;;) {
1595     MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_READ, "execve *argv");
1596     s = *p++;
1597     if (NULL == s)
1598       break;
1599     n = strlen (s);
1600     MF_VALIDATE_EXTENT (s, CLAMPADD(n, 1), __MF_CHECK_READ, "execve **argv");
1601   }
1602
1603   for (p = envp;;) {
1604     MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_READ, "execve *envp");
1605     s = *p++;
1606     if (NULL == s)
1607       break;
1608     n = strlen (s);
1609     MF_VALIDATE_EXTENT (s, CLAMPADD(n, 1), __MF_CHECK_READ, "execve **envp");
1610   }
1611   return execve (path, argv, envp);
1612 }
1613
1614
1615 WRAPPER2(int, execv, const char *path, char *const argv [])
1616 {
1617   size_t n;
1618   char *const *p;
1619   const char *s;
1620   TRACE ("%s\n", __PRETTY_FUNCTION__);
1621
1622   n = strlen (path);
1623   MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "execv path");
1624
1625   for (p = argv;;) {
1626     MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_READ, "execv *argv");
1627     s = *p++;
1628     if (NULL == s)
1629       break;
1630     n = strlen (s);
1631     MF_VALIDATE_EXTENT (s, CLAMPADD(n, 1), __MF_CHECK_READ, "execv **argv");
1632   }
1633   return execv (path, argv);
1634 }
1635
1636
1637 WRAPPER2(int, execvp, const char *path, char *const argv [])
1638 {
1639   size_t n;
1640   char *const *p;
1641   const char *s;
1642   TRACE ("%s\n", __PRETTY_FUNCTION__);
1643
1644   n = strlen (path);
1645   MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "execvp path");
1646
1647   for (p = argv;;) {
1648     MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_READ, "execvp *argv");
1649     s = *p++;
1650     if (NULL == s)
1651       break;
1652     n = strlen (s);
1653     MF_VALIDATE_EXTENT (s, CLAMPADD(n, 1), __MF_CHECK_READ, "execvp **argv");
1654   }
1655   return execvp (path, argv);
1656 }
1657
1658
1659 WRAPPER2(int, system, const char *string)
1660 {
1661   size_t n;
1662   TRACE ("%s\n", __PRETTY_FUNCTION__);
1663   n = strlen (string);
1664   MF_VALIDATE_EXTENT (string, CLAMPADD(n, 1), __MF_CHECK_READ,
1665     "system string");
1666   return system (string);
1667 }
1668
1669
1670 WRAPPER2(void *, dlopen, const char *path, int flags)
1671 {
1672   void *p;
1673   size_t n;
1674   TRACE ("%s\n", __PRETTY_FUNCTION__);
1675   n = strlen (path);
1676   MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "dlopen path");
1677   p = dlopen (path, flags);
1678   if (NULL != p) {
1679 #ifdef MF_REGISTER_dlopen
1680     __mf_register (p, 0, MF_REGISTER_dlopen, "dlopen result");
1681 #endif
1682     MF_VALIDATE_EXTENT (p, 0, __MF_CHECK_WRITE, "dlopen result");
1683   }
1684   return p;
1685 }
1686
1687
1688 WRAPPER2(int, dlclose, void *handle)
1689 {
1690   int resp;
1691   TRACE ("%s\n", __PRETTY_FUNCTION__);
1692   MF_VALIDATE_EXTENT (handle, 0, __MF_CHECK_READ, "dlclose handle");
1693   resp = dlclose (handle);
1694 #ifdef MF_REGISTER_dlopen
1695   __mf_unregister (handle, 0, MF_REGISTER_dlopen);
1696 #endif
1697   return resp;
1698 }
1699
1700
1701 WRAPPER2(char *, dlerror)
1702 {
1703   char *p;
1704   TRACE ("%s\n", __PRETTY_FUNCTION__);
1705   p = dlerror ();
1706   if (NULL != p) {
1707     size_t n;
1708     n = strlen (p);
1709     n = CLAMPADD(n, 1);
1710 #ifdef MF_REGISTER_dlerror
1711     __mf_register (p, n, MF_REGISTER_dlerror, "dlerror result");
1712 #endif
1713     MF_VALIDATE_EXTENT (p, n, __MF_CHECK_WRITE, "dlerror result");
1714   }
1715   return p;
1716 }
1717
1718
1719 WRAPPER2(void *, dlsym, void *handle, char *symbol)
1720 {
1721   size_t n;
1722   void *p;
1723   TRACE ("%s\n", __PRETTY_FUNCTION__);
1724   MF_VALIDATE_EXTENT (handle, 0, __MF_CHECK_READ, "dlsym handle");
1725   n = strlen (symbol);
1726   MF_VALIDATE_EXTENT (symbol, CLAMPADD(n, 1), __MF_CHECK_READ, "dlsym symbol");
1727   p = dlsym (handle, symbol);
1728   if (NULL != p) {
1729 #ifdef MF_REGISTER_dlsym
1730     __mf_register (p, 0, MF_REGISTER_dlsym, "dlsym result");
1731 #endif
1732     MF_VALIDATE_EXTENT (p, 0, __MF_CHECK_WRITE, "dlsym result");
1733   }
1734   return p;
1735 }
1736
1737
1738 #if defined (HAVE_SYS_IPC_H) && defined (HAVE_SYS_SEM_H) && defined (HAVE_SYS_SHM_H)
1739
1740 WRAPPER2(int, semop, int semid, struct sembuf *sops, unsigned nsops)
1741 {
1742   TRACE ("%s\n", __PRETTY_FUNCTION__);
1743   MF_VALIDATE_EXTENT (sops, sizeof (*sops) * nsops, __MF_CHECK_READ,
1744     "semop sops");
1745   return semop (semid, sops, nsops);
1746 }
1747
1748
1749 #ifndef HAVE_UNION_SEMUN
1750 union semun {
1751         int val;                        /* value for SETVAL */
1752         struct semid_ds *buf;           /* buffer for IPC_STAT, IPC_SET */
1753         unsigned short int *array;      /* array for GETALL, SETALL */
1754         struct seminfo *__buf;          /* buffer for IPC_INFO */
1755 };
1756 #endif
1757 WRAPPER2(int, semctl, int semid, int semnum, int cmd, union semun arg)
1758 {
1759   TRACE ("%s\n", __PRETTY_FUNCTION__);
1760   switch (cmd) {
1761   case IPC_STAT:
1762     MF_VALIDATE_EXTENT (arg.buf, sizeof (*arg.buf), __MF_CHECK_WRITE,
1763       "semctl buf");
1764     break;
1765   case IPC_SET:
1766     MF_VALIDATE_EXTENT (arg.buf, sizeof (*arg.buf), __MF_CHECK_READ,
1767       "semctl buf");
1768     break;
1769   case GETALL:
1770     MF_VALIDATE_EXTENT (arg.array, sizeof (*arg.array), __MF_CHECK_WRITE,
1771       "semctl array");
1772   case SETALL:
1773     MF_VALIDATE_EXTENT (arg.array, sizeof (*arg.array), __MF_CHECK_READ,
1774       "semctl array");
1775     break;
1776 #ifdef IPC_INFO
1777   /* FreeBSD 5.1 And Cygwin headers include IPC_INFO but not the __buf field.  */
1778 #if !defined(__FreeBSD__) && !defined(__CYGWIN__)
1779   case IPC_INFO:
1780     MF_VALIDATE_EXTENT (arg.__buf, sizeof (*arg.__buf), __MF_CHECK_WRITE,
1781       "semctl __buf");
1782     break;
1783 #endif
1784 #endif
1785   default:
1786     break;
1787   }
1788   return semctl (semid, semnum, cmd, arg);
1789 }
1790
1791
1792 WRAPPER2(int, shmctl, int shmid, int cmd, struct shmid_ds *buf)
1793 {
1794   TRACE ("%s\n", __PRETTY_FUNCTION__);
1795   switch (cmd) {
1796   case IPC_STAT:
1797     MF_VALIDATE_EXTENT (buf, sizeof (*buf), __MF_CHECK_WRITE,
1798       "shmctl buf");
1799     break;
1800   case IPC_SET:
1801     MF_VALIDATE_EXTENT (buf, sizeof (*buf), __MF_CHECK_READ,
1802       "shmctl buf");
1803     break;
1804   default:
1805     break;
1806   }
1807   return shmctl (shmid, cmd, buf);
1808 }
1809
1810
1811 WRAPPER2(void *, shmat, int shmid, const void *shmaddr, int shmflg)
1812 {
1813   void *p;
1814   TRACE ("%s\n", __PRETTY_FUNCTION__);
1815   p = shmat (shmid, shmaddr, shmflg);
1816 #ifdef MF_REGISTER_shmat
1817   if (NULL != p) {
1818     struct shmid_ds buf;
1819     __mf_register (p, shmctl (shmid, IPC_STAT, &buf) ? 0 : buf.shm_segsz,
1820       MF_REGISTER_shmat, "shmat result");
1821   }
1822 #endif
1823   return p;
1824 }
1825
1826
1827 WRAPPER2(int, shmdt, const void *shmaddr)
1828 {
1829   int resp;
1830   TRACE ("%s\n", __PRETTY_FUNCTION__);
1831   resp = shmdt (shmaddr);
1832 #ifdef MF_REGISTER_shmat
1833   __mf_unregister ((void *)shmaddr, 0, MF_REGISTER_shmat);
1834 #endif
1835   return resp;
1836 }
1837
1838
1839 #endif /* HAVE_SYS_IPC/SEM/SHM_H */
1840
1841
1842
1843 /* ctype stuff.  This is host-specific by necessity, as the arrays
1844    that is used by most is*()/to*() macros are implementation-defined.  */
1845
1846 /* GLIBC 2.3 */
1847 #ifdef HAVE___CTYPE_B_LOC
1848 WRAPPER2(unsigned short **, __ctype_b_loc, void)
1849 {
1850   static unsigned short * last_buf = (void *) 0;
1851   static unsigned short ** last_ptr = (void *) 0;
1852   unsigned short ** ptr = (unsigned short **) __ctype_b_loc ();
1853   unsigned short * buf = * ptr;
1854   if (ptr != last_ptr)
1855     {
1856       /* XXX: unregister last_ptr? */
1857       last_ptr = ptr;
1858       __mf_register (last_ptr, sizeof(last_ptr), __MF_TYPE_STATIC, "ctype_b_loc **");
1859     }
1860   if (buf != last_buf)
1861     {
1862       last_buf = buf;
1863       __mf_register ((void *) (last_buf - 128), 384 * sizeof(unsigned short), __MF_TYPE_STATIC,
1864                      "ctype_b_loc []");
1865     }
1866   return ptr;
1867 }
1868 #endif
1869
1870 #ifdef HAVE___CTYPE_TOUPPER_LOC
1871 WRAPPER2(int **, __ctype_toupper_loc, void)
1872 {
1873   static int * last_buf = (void *) 0;
1874   static int ** last_ptr = (void *) 0;
1875   int ** ptr = (int **) __ctype_toupper_loc ();
1876   int * buf = * ptr;
1877   if (ptr != last_ptr)
1878     {
1879       /* XXX: unregister last_ptr? */
1880       last_ptr = ptr;
1881       __mf_register (last_ptr, sizeof(last_ptr), __MF_TYPE_STATIC, "ctype_toupper_loc **");
1882     }
1883   if (buf != last_buf)
1884     {
1885       last_buf = buf;
1886       __mf_register ((void *) (last_buf - 128), 384 * sizeof(int), __MF_TYPE_STATIC,
1887                      "ctype_toupper_loc []");
1888     }
1889   return ptr;
1890 }
1891 #endif
1892
1893 #ifdef HAVE___CTYPE_TOLOWER_LOC
1894 WRAPPER2(int **, __ctype_tolower_loc, void)
1895 {
1896   static int * last_buf = (void *) 0;
1897   static int ** last_ptr = (void *) 0;
1898   int ** ptr = (int **) __ctype_tolower_loc ();
1899   int * buf = * ptr;
1900   if (ptr != last_ptr)
1901     {
1902       /* XXX: unregister last_ptr? */
1903       last_ptr = ptr;
1904       __mf_register (last_ptr, sizeof(last_ptr), __MF_TYPE_STATIC, "ctype_tolower_loc **");
1905     }
1906   if (buf != last_buf)
1907     {
1908       last_buf = buf;
1909       __mf_register ((void *) (last_buf - 128), 384 * sizeof(int), __MF_TYPE_STATIC,
1910                      "ctype_tolower_loc []");
1911     }
1912   return ptr;
1913 }
1914 #endif
1915
1916
1917 /* passwd/group related functions.  These register every (static) pointer value returned,
1918    and rely on libmudflap's quiet toleration of duplicate static registrations.  */
1919
1920 #ifdef HAVE_GETLOGIN
1921 WRAPPER2(char *, getlogin, void)
1922 {
1923   char *buf = getlogin ();
1924   if (buf != NULL)
1925     __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
1926                    "getlogin() return");
1927   return buf;
1928 }
1929 #endif
1930
1931
1932 #ifdef HAVE_CUSERID
1933 WRAPPER2(char *, cuserid, char * buf)
1934 {
1935   if (buf != NULL)
1936     {
1937       MF_VALIDATE_EXTENT(buf, L_cuserid, __MF_CHECK_WRITE,
1938                          "cuserid destination");
1939       return cuserid (buf);
1940     }
1941   buf = cuserid (NULL);
1942   if (buf != NULL)
1943     __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
1944                    "getcuserid() return");
1945   return buf;
1946 }
1947 #endif
1948
1949
1950 #ifdef HAVE_GETPWNAM
1951 WRAPPER2(struct passwd *, getpwnam, const char *name)
1952 {
1953   struct passwd *buf;
1954   MF_VALIDATE_EXTENT(name, strlen(name)+1, __MF_CHECK_READ,
1955                      "getpwnam name");
1956   buf = getpwnam (name);
1957   if (buf != NULL)
1958     __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
1959                    "getpw*() return");
1960   return buf;
1961 }
1962 #endif
1963
1964
1965 #ifdef HAVE_GETPWUID
1966 WRAPPER2(struct passwd *, getpwuid, uid_t uid)
1967 {
1968   struct passwd *buf;
1969   buf = getpwuid (uid);
1970   if (buf != NULL)
1971     __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
1972                    "getpw*() return");
1973   return buf;
1974 }
1975 #endif
1976
1977
1978 #ifdef HAVE_GETGRNAM
1979 WRAPPER2(struct group *, getgrnam, const char *name)
1980 {
1981   struct group *buf;
1982   MF_VALIDATE_EXTENT(name, strlen(name)+1, __MF_CHECK_READ,
1983                      "getgrnam name");
1984   buf = getgrnam (name);
1985   if (buf != NULL)
1986     __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
1987                    "getgr*() return");
1988   return buf;
1989 }
1990 #endif
1991
1992
1993 #ifdef HAVE_GETGRGID
1994 WRAPPER2(struct group *, getgrgid, uid_t uid)
1995 {
1996   struct group *buf;
1997   buf = getgrgid (uid);
1998   if (buf != NULL)
1999     __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
2000                    "getgr*() return");
2001   return buf;
2002 }
2003 #endif
2004
2005
2006 #ifdef HAVE_GETSERVENT
2007 WRAPPER2(struct servent *, getservent, void)
2008 {
2009   struct servent *buf;
2010   buf = getservent ();
2011   if (buf != NULL)
2012     __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
2013                    "getserv*() return");
2014   return buf;
2015 }
2016 #endif
2017
2018
2019 #ifdef HAVE_GETSERVBYNAME
2020 WRAPPER2(struct servent *, getservbyname, const char *name, const char *proto)
2021 {
2022   struct servent *buf;
2023   MF_VALIDATE_EXTENT(name, strlen(name)+1, __MF_CHECK_READ,
2024                      "getservbyname name");
2025   MF_VALIDATE_EXTENT(proto, strlen(proto)+1, __MF_CHECK_READ,
2026                      "getservbyname proto");
2027   buf = getservbyname (name, proto);
2028   if (buf != NULL)
2029     __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
2030                    "getserv*() return");
2031   return buf;
2032 }
2033 #endif
2034
2035
2036 #ifdef HAVE_GETSERVBYPORT
2037 WRAPPER2(struct servent *, getservbyport, int port, const char *proto)
2038 {
2039   struct servent *buf;
2040   MF_VALIDATE_EXTENT(proto, strlen(proto)+1, __MF_CHECK_READ,
2041                      "getservbyport proto");
2042   buf = getservbyport (port, proto);
2043   if (buf != NULL)
2044     __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
2045                    "getserv*() return");
2046   return buf;
2047 }
2048 #endif
2049
2050
2051 #ifdef HAVE_GAI_STRERROR
2052 WRAPPER2(const char *, gai_strerror, int errcode)
2053 {
2054   const char *buf;
2055   buf = gai_strerror (errcode);
2056   if (buf != NULL)
2057     __mf_register ((void *) buf, strlen(buf)+1, __MF_TYPE_STATIC,
2058                    "gai_strerror() return");
2059   return buf;
2060 }
2061 #endif
2062
2063
2064 #ifdef HAVE_GETMNTENT
2065 WRAPPER2(struct mntent *, getmntent, FILE *filep)
2066 {
2067   struct mntent *m;
2068   static struct mntent *last = NULL;
2069
2070   MF_VALIDATE_EXTENT (filep, sizeof (*filep), __MF_CHECK_WRITE,
2071     "getmntent stream");
2072 #define UR(field) __mf_unregister(last->field, strlen (last->field)+1, __MF_TYPE_STATIC)
2073   if (last)
2074     {
2075       UR (mnt_fsname);
2076       UR (mnt_dir);
2077       UR (mnt_type);
2078       UR (mnt_opts);
2079       __mf_unregister (last, sizeof (*last), __MF_TYPE_STATIC);
2080     }
2081 #undef UR
2082
2083   m = getmntent (filep);
2084   last = m;
2085
2086 #define R(field) __mf_register(last->field, strlen (last->field)+1, __MF_TYPE_STATIC, "mntent " #field)
2087   if (m)
2088     {
2089       R (mnt_fsname);
2090       R (mnt_dir);
2091       R (mnt_type);
2092       R (mnt_opts);
2093       __mf_register (last, sizeof (*last), __MF_TYPE_STATIC, "getmntent result");
2094     }
2095 #undef R
2096
2097   return m;
2098 }
2099 #endif
2100
2101
2102 #ifdef HAVE_INET_NTOA
2103 WRAPPER2(char *, inet_ntoa, struct in_addr in)
2104 {
2105   static char *last_buf = NULL;
2106   char *buf;
2107   if (last_buf)
2108     __mf_unregister (last_buf, strlen (last_buf)+1, __MF_TYPE_STATIC);
2109   buf = inet_ntoa (in);
2110   last_buf = buf;
2111   if (buf)
2112     __mf_register (last_buf, strlen (last_buf)+1, __MF_TYPE_STATIC, "inet_ntoa result");
2113   return buf;
2114 }
2115 #endif
2116
2117
2118 #ifdef HAVE_GETPROTOENT
2119 WRAPPER2(struct protoent *, getprotoent, void)
2120 {
2121   struct protoent *buf;
2122   buf = getprotoent ();
2123   if (buf != NULL)
2124     __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC, "getproto*() return");
2125   return buf;
2126 }
2127 #endif
2128
2129
2130 #ifdef HAVE_GETPROTOBYNAME
2131 WRAPPER2(struct protoent *, getprotobyname, const char *name)
2132 {
2133   struct protoent *buf;
2134   MF_VALIDATE_EXTENT(name, strlen(name)+1, __MF_CHECK_READ,
2135                      "getprotobyname name");
2136   buf = getprotobyname (name);
2137   if (buf != NULL)
2138     __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
2139                    "getproto*() return");
2140   return buf;
2141 }
2142 #endif
2143
2144
2145 #ifdef HAVE_GETPROTOBYNUMBER
2146 WRAPPER2(struct protoent *, getprotobynumber, int port)
2147 {
2148   struct protoent *buf;
2149   buf = getprotobynumber (port);
2150   if (buf != NULL)
2151     __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
2152                    "getproto*() return");
2153   return buf;
2154 }
2155 #endif