]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Fix the access_extended wrapper, which was rather broken. That's what I get
authorNicholas Nethercote <njn@valgrind.org>
Sun, 16 Aug 2009 00:00:17 +0000 (00:00 +0000)
committerNicholas Nethercote <njn@valgrind.org>
Sun, 16 Aug 2009 00:00:17 +0000 (00:00 +0000)
for not testing properly.  Added a regtest for it too.  Fixes bug 200760
(again, properly this time).

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@10826

coregrind/m_syswrap/syswrap-darwin.c
none/tests/darwin/Makefile.am
none/tests/darwin/access_extended.c [new file with mode: 0644]
none/tests/darwin/access_extended.stderr.exp [new file with mode: 0644]
none/tests/darwin/access_extended.vgtest [new file with mode: 0644]

index 23dacb892dbc8b99beed0771eca384b735f777b6..86c974f9ae22c306a57d1dc6662a6c9b0286d644 100644 (file)
@@ -2069,6 +2069,9 @@ PRE(access_extended)
 {
    PRINT("access_extended( %#lx(%s), %lu, %#lx, %lu )",
       ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
+   // XXX: the accessx_descriptor struct contains padding, so this can cause
+   // unnecessary undefined value errors.  But you arguably shouldn't be
+   // passing undefined values to the kernel anyway...
    PRE_REG_READ4(int, "access_extended", void *, entries, vki_size_t, size, 
                  vki_errno_t *, results, vki_uid_t *, uid);
    PRE_MEM_READ("access_extended(entries)", ARG1, ARG2 );
@@ -2084,18 +2087,17 @@ POST(access_extended)
    // shortest possible string section.  The shortest string section allowed
    // consists of a single one-char string (plus the NUL char).  Hence the
    // '2'.
-   struct vki_accessx_descriptor* entries = (struct vki_accessx_descriptor*)ARG2;
+   struct vki_accessx_descriptor* entries = (struct vki_accessx_descriptor*)ARG1;
    SizeT size = ARG2;
    Int n_descs = (size - 2) / sizeof(struct accessx_descriptor);
-   Int i = 0;     // Current position in the descriptors section array.
+   Int i;         // Current position in the descriptors section array.
    Int u;         // Upper bound on the length of the descriptors array
-                  // (recomputed each time around the loop)
+                  //   (recomputed each time around the loop)
    vg_assert(n_descs > 0);
 
    // Step through the descriptors, lowering 'n_descs' until we know we've
    // reached the string section.
-   while (True)
-   {
+   for (i = 0; True; i++) {
       // If we're past our estimate, we must be one past the end of the
       // descriptors section (ie. at the start of the string section).  Stop.
       if (i >= n_descs)
index 3d06695ce00fe72875722542ce2acf18e3fbb05b..391fb59996beac2def80db0f66993f544578e45e 100644 (file)
@@ -4,10 +4,12 @@ include $(top_srcdir)/Makefile.tool-tests.am
 dist_noinst_SCRIPTS = filter_stderr
 
 EXTRA_DIST = \
+       access_extended.stderr.exp access_extended.vgtest \
        apple-main-arg.stderr.exp apple-main-arg.vgtest \
        rlimit.stderr.exp rlimit.vgtest
 
 check_PROGRAMS = \
+       access_extended \
        apple-main-arg \
        rlimit
 
diff --git a/none/tests/darwin/access_extended.c b/none/tests/darwin/access_extended.c
new file mode 100644 (file)
index 0000000..bf56154
--- /dev/null
@@ -0,0 +1,48 @@
+// This is a test for access_extended(), one of the more ridiculous syscalls
+// ever devised.  For bug 200760.  See the comments on the wrapper in
+// syswrap-darwin.c to understand what is going on here.
+
+#include <sys/syscall.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int main(void)
+{
+   char* name1 = "access_extended.c";
+   char* name2 = "no_such_file";
+   // Space for three descriptors and the two strings (and NUL chars for them).
+   size_t entries_szB =
+      sizeof(struct accessx_descriptor) * 3 +
+      strlen(name1) + 1 +
+      strlen(name2) + 1;
+   struct accessx_descriptor* entries = malloc(entries_szB);
+   char* string1 = (char*)&entries[3];
+   char* string2 = string1 + strlen(name1) + 1;
+   int results[3];
+   int retval;
+
+   entries[0].ad_name_offset = string1 - (char*)entries;
+   entries[1].ad_name_offset = 0;   // reuse the previous entry's string
+   entries[2].ad_name_offset = string2 - (char*)entries;
+   entries[0].ad_flags       = F_OK;      // succeeds
+   entries[1].ad_flags       = X_OK;      // fails
+   entries[2].ad_flags       = F_OK;      // fails
+   strcpy(string1, name1);
+   strcpy(string2, name2);
+
+   retval = syscall(SYS_access_extended, entries, entries_szB, results,
+                    /*uid--unused?*/0);
+
+   fprintf(stderr, "retval = %d\n", retval);
+   fprintf(stderr, "%s(F_OK) = %d (%s)\n",
+      name1, results[0], strerror(results[0]));
+   fprintf(stderr, "%s(X_OK) = %d (%s)\n",
+      name1, results[1], strerror(results[1]));
+   fprintf(stderr, "%s(F_OK) = %d (%s)\n",
+      name2, results[2], strerror(results[2]));
+
+   return 0;
+}
+
diff --git a/none/tests/darwin/access_extended.stderr.exp b/none/tests/darwin/access_extended.stderr.exp
new file mode 100644 (file)
index 0000000..65438c5
--- /dev/null
@@ -0,0 +1,4 @@
+retval = 0
+access_extended.c(F_OK) = 0 (Unknown error: 0)
+access_extended.c(X_OK) = 13 (Permission denied)
+no_such_file(F_OK) = 2 (No such file or directory)
diff --git a/none/tests/darwin/access_extended.vgtest b/none/tests/darwin/access_extended.vgtest
new file mode 100644 (file)
index 0000000..29257b1
--- /dev/null
@@ -0,0 +1,2 @@
+prog: access_extended
+vgopts: -q