]> granicus.if.org Git - strace/blob - open.c
Robustify mpers.awk against invalid input
[strace] / open.c
1 #include "defs.h"
2
3 #include <fcntl.h>
4
5 #ifdef O_LARGEFILE
6 # if O_LARGEFILE == 0          /* biarch platforms in 64-bit mode */
7 #  undef O_LARGEFILE
8 #  ifdef SPARC64
9 #   define O_LARGEFILE 0x40000
10 #  elif defined X86_64 || defined S390X
11 #   define O_LARGEFILE 0100000
12 #  endif
13 # endif
14 #endif
15
16 #include "xlat/open_access_modes.h"
17 #include "xlat/open_mode_flags.h"
18
19 #ifndef AT_FDCWD
20 # define AT_FDCWD                -100
21 #endif
22
23 /* The fd is an "int", so when decoding x86 on x86_64, we need to force sign
24  * extension to get the right value.  We do this by declaring fd as int here.
25  */
26 void
27 print_dirfd(struct tcb *tcp, int fd)
28 {
29         if (fd == AT_FDCWD)
30                 tprints("AT_FDCWD, ");
31         else {
32                 printfd(tcp, fd);
33                 tprints(", ");
34         }
35 }
36
37 /*
38  * low bits of the open(2) flags define access mode,
39  * other bits are real flags.
40  */
41 const char *
42 sprint_open_modes(int flags)
43 {
44         static char outstr[(1 + ARRAY_SIZE(open_mode_flags)) * sizeof("O_LARGEFILE")];
45         char *p;
46         char sep;
47         const char *str;
48         const struct xlat *x;
49
50         sep = ' ';
51         p = stpcpy(outstr, "flags");
52         str = xlookup(open_access_modes, flags & 3);
53         if (str) {
54                 *p++ = sep;
55                 p = stpcpy(p, str);
56                 flags &= ~3;
57                 if (!flags)
58                         return outstr;
59                 sep = '|';
60         }
61
62         for (x = open_mode_flags; x->str; x++) {
63                 if ((flags & x->val) == x->val) {
64                         *p++ = sep;
65                         p = stpcpy(p, x->str);
66                         flags &= ~x->val;
67                         if (!flags)
68                                 return outstr;
69                         sep = '|';
70                 }
71         }
72         /* flags is still nonzero */
73         *p++ = sep;
74         sprintf(p, "%#x", flags);
75         return outstr;
76 }
77
78 void
79 tprint_open_modes(int flags)
80 {
81         tprints(sprint_open_modes(flags) + sizeof("flags"));
82 }
83
84 static int
85 decode_open(struct tcb *tcp, int offset)
86 {
87         printpath(tcp, tcp->u_arg[offset]);
88         tprints(", ");
89         /* flags */
90         tprint_open_modes(tcp->u_arg[offset + 1]);
91         if (tcp->u_arg[offset + 1] & O_CREAT) {
92                 /* mode */
93                 tprintf(", %#lo", tcp->u_arg[offset + 2]);
94         }
95
96         return RVAL_DECODED | RVAL_FD;
97 }
98
99 SYS_FUNC(open)
100 {
101         return decode_open(tcp, 0);
102 }
103
104 SYS_FUNC(openat)
105 {
106         print_dirfd(tcp, tcp->u_arg[0]);
107         return decode_open(tcp, 1);
108 }
109
110 SYS_FUNC(creat)
111 {
112         printpath(tcp, tcp->u_arg[0]);
113         tprintf(", %#lo", tcp->u_arg[1]);
114
115         return RVAL_DECODED | RVAL_FD;
116 }