aboutsummaryrefslogtreecommitdiff
path: root/test/libelf/tset
diff options
context:
space:
mode:
authorEd Maste <emaste@FreeBSD.org>2019-06-29 15:27:18 +0000
committerEd Maste <emaste@FreeBSD.org>2019-06-29 15:27:18 +0000
commita5b08c1484eac2c6a65e726f550b3189ff84c6c8 (patch)
tree01cd9d6d76e2c378b391422460c6f233ead08179 /test/libelf/tset
parent2b92b30119ed91ed88f102ba9ecc40cd1c046a65 (diff)
Import ELF Tool Chain snapshot at r3769vendor/elftoolchain/elftoolchain-r3769vendor/elftoolchain
Notes
Notes: svn path=/vendor/elftoolchain/dist/; revision=349544 svn path=/vendor/elftoolchain/elftoolchain-r3769/; revision=349545; tag=vendor/elftoolchain/elftoolchain-r3769
Diffstat (limited to 'test/libelf/tset')
-rw-r--r--test/libelf/tset/Makefile3
-rwxr-xr-xtest/libelf/tset/bin/elfc16
-rw-r--r--test/libelf/tset/common/Makefile3
-rw-r--r--test/libelf/tset/common/ehdr-malformed-1.yaml23
-rw-r--r--test/libelf/tset/common/ehdr_template.m450
-rw-r--r--test/libelf/tset/elf32_getehdr/Makefile4
-rw-r--r--test/libelf/tset/elf32_newehdr/Makefile3
-rw-r--r--test/libelf/tset/elf64_getehdr/Makefile4
-rw-r--r--test/libelf/tset/elf64_newehdr/Makefile3
-rw-r--r--test/libelf/tset/elf_begin/Makefile3
-rw-r--r--test/libelf/tset/elf_begin/begin.m443
-rw-r--r--test/libelf/tset/elf_begin/entry-too-large.ar3
-rw-r--r--test/libelf/tset/elf_getdata/getdata.m4176
-rw-r--r--test/libelf/tset/elf_rand/Makefile18
-rw-r--r--test/libelf/tset/elf_rand/empty-file.ar2
-rw-r--r--test/libelf/tset/elf_rand/missing-file.ar2
-rw-r--r--test/libelf/tset/elf_rand/rand.m4415
17 files changed, 743 insertions, 28 deletions
diff --git a/test/libelf/tset/Makefile b/test/libelf/tset/Makefile
index 63e958691306..5a5e96f6ebd1 100644
--- a/test/libelf/tset/Makefile
+++ b/test/libelf/tset/Makefile
@@ -1,5 +1,5 @@
#
-# $Id: Makefile 3025 2014-04-18 16:20:25Z jkoshy $
+# $Id: Makefile 3715 2019-03-18 09:15:40Z jkoshy $
#
TOP= ../../..
@@ -36,6 +36,7 @@ SUBDIR+= elf_ndxscn
SUBDIR+= elf_next
SUBDIR+= elf_newscn
SUBDIR+= elf_nextscn
+SUBDIR+= elf_rand
SUBDIR+= elf_rawfile
SUBDIR+= elf_strptr
SUBDIR+= elf_update
diff --git a/test/libelf/tset/bin/elfc b/test/libelf/tset/bin/elfc
index 98995e820e26..4c77e4220b18 100755
--- a/test/libelf/tset/bin/elfc
+++ b/test/libelf/tset/bin/elfc
@@ -74,7 +74,7 @@
# sections, a section index may be manually specified using a
# 'sh_index' pseudo field.
#
-# $Id: elfc 3614 2018-04-21 19:48:04Z jkoshy $
+# $Id: elfc 3689 2019-02-23 22:50:51Z jkoshy $
version = "%prog 1.0"
usage = "usage: %prog [options] [input-file]"
@@ -442,6 +442,14 @@ def check_dict(d, l, node=None):
raise ElfError(node, "{%s} Unknown key(s) %s" % \
(node.tag, unknown))
+def bounded_value(v, encoding):
+ """Return the value of 'v' bounded to the maximum size for a type."""
+ if encoding == "H":
+ return (v & 0xFFFF)
+ elif encoding == "I":
+ return (v & 0xFFFFFFFF)
+ return v
+
#
# Helper classes.
#
@@ -559,8 +567,10 @@ class ElfType:
else:
n = 3
for t in self.fields:
- if t[n] != "":
- a.append(getattr(self, t[0]))
+ field_encoding = t[n]
+ if field_encoding != "":
+ v = getattr(self, t[0])
+ a.append(bounded_value(v, field_encoding))
return tuple(a)
def getfields(self, elfclass):
diff --git a/test/libelf/tset/common/Makefile b/test/libelf/tset/common/Makefile
index 5dd5bf9c1a5b..8f8400a39753 100644
--- a/test/libelf/tset/common/Makefile
+++ b/test/libelf/tset/common/Makefile
@@ -1,10 +1,11 @@
-# $Id: Makefile 1719 2011-08-12 08:24:14Z jkoshy $
+# $Id: Makefile 3690 2019-02-23 22:51:13Z jkoshy $
TOP= ../../../..
YAML_FILES= check_elf \
getclass \
ehdr \
+ ehdr-malformed-1 \
fsize \
newehdr newscn newscn2 \
phdr \
diff --git a/test/libelf/tset/common/ehdr-malformed-1.yaml b/test/libelf/tset/common/ehdr-malformed-1.yaml
new file mode 100644
index 000000000000..d7c000f47aed
--- /dev/null
+++ b/test/libelf/tset/common/ehdr-malformed-1.yaml
@@ -0,0 +1,23 @@
+%YAML 1.1
+# $Id$
+---
+ehdr: !Ehdr
+ e_ident: !Ident # e_ident[] members
+ ei_class: ELFCLASSNONE
+ ei_data: ELFDATANONE
+ ei_osabi: ELFOSABI_SYSV
+ ei_abiversion: 0
+ # other members
+ e_type: 0xFF03
+ e_machine: 0x42
+ e_version: 0xFFFFFFFF
+ e_entry: 0xFFFFFFFFFFFFFFFF
+ e_phoff: 0xFFFFFFFFFFFFFFFF
+ e_shoff: 0xFFFFFFFFFFFFFFFF
+ e_flags: [ 64, 8, 2, 1]
+ e_ehsize: 62
+ e_phentsize: 228
+ e_phnum: 0
+ e_shentsize: 8192
+ e_shnum: 0
+ e_shstrndx: 0
diff --git a/test/libelf/tset/common/ehdr_template.m4 b/test/libelf/tset/common/ehdr_template.m4
index 872e0ff3b7c8..31cacd4de541 100644
--- a/test/libelf/tset/common/ehdr_template.m4
+++ b/test/libelf/tset/common/ehdr_template.m4
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: ehdr_template.m4 3174 2015-03-27 17:13:41Z emaste $
+ * $Id: ehdr_template.m4 3703 2019-03-02 20:41:03Z jkoshy $
*/
include(`elfts.m4')
@@ -367,3 +367,51 @@ tcElfWrongSize$1(void)
FN(`LSB')
FN(`MSB')
+
+/*
+ * Verify that malformed ELF objects are rejected.
+ */
+
+undefine(`FN')
+define(`FN',`
+void
+tcMalformed1$1(void)
+{
+ int error, fd, result;
+ Elf *e;
+ char *fn;
+ TS_EHDR *eh;
+
+ TP_CHECK_INITIALIZATION();
+
+ TP_ANNOUNCE("TS_ICNAME with a malformed ELF header "
+ "fails with ELF_E_HEADER.");
+
+ e = NULL;
+ fd = -1;
+ fn = "ehdr-malformed-1.TOLOWER($1)`'TS_EHDRSZ";
+ result = TET_UNRESOLVED;
+
+ _TS_OPEN_FILE(e, fn, ELF_C_READ, fd, goto done;);
+
+ error = 0;
+ if ((eh = TS_ICFUNC`'(e)) != NULL) {
+ TP_FAIL("\"%s\" TS_ICNAME`'() succeeded.", fn);
+ goto done;
+ } else if ((error = elf_errno()) != ELF_E_HEADER) {
+ TP_FAIL("\"%s\" incorrect error (%d).", fn, error);
+ goto done;
+ }
+
+ result = TET_PASS;
+
+done:
+ if (e)
+ (void) elf_end(e);
+ if (fd != -1)
+ (void) close(fd);
+ tet_result(result);
+}')
+
+FN(`LSB')
+FN(`MSB')
diff --git a/test/libelf/tset/elf32_getehdr/Makefile b/test/libelf/tset/elf32_getehdr/Makefile
index 8285b1f8ed6e..1b01505e750c 100644
--- a/test/libelf/tset/elf32_getehdr/Makefile
+++ b/test/libelf/tset/elf32_getehdr/Makefile
@@ -1,8 +1,8 @@
-# $Id: Makefile 1368 2011-01-22 09:09:15Z jkoshy $
+# $Id: Makefile 3691 2019-02-23 23:34:04Z jkoshy $
TOP= ../../../..
TS_SRCS= ehdr.m4
-TS_YAML= ehdr
+TS_YAML= ehdr ehdr-malformed-1
.include "${TOP}/mk/elftoolchain.tet.mk"
diff --git a/test/libelf/tset/elf32_newehdr/Makefile b/test/libelf/tset/elf32_newehdr/Makefile
index 78c4f1238af3..7c109199cf4f 100644
--- a/test/libelf/tset/elf32_newehdr/Makefile
+++ b/test/libelf/tset/elf32_newehdr/Makefile
@@ -1,9 +1,10 @@
-# $Id: Makefile 1358 2011-01-08 05:40:41Z jkoshy $
+# $Id: Makefile 3702 2019-03-02 20:40:55Z jkoshy $
TOP= ../../../..
TS_SRCS= ehdr.m4
TS_DATA= ehdr.msb32 ehdr.lsb32 ehdr.msb64 ehdr.lsb64 \
+ ehdr-malformed-1.lsb32 ehdr-malformed-1.msb32 \
newehdr.lsb32 newehdr.msb32
.include "${TOP}/mk/elftoolchain.tet.mk"
diff --git a/test/libelf/tset/elf64_getehdr/Makefile b/test/libelf/tset/elf64_getehdr/Makefile
index e8bb49ad4d25..1b01505e750c 100644
--- a/test/libelf/tset/elf64_getehdr/Makefile
+++ b/test/libelf/tset/elf64_getehdr/Makefile
@@ -1,8 +1,8 @@
-# $Id: Makefile 1358 2011-01-08 05:40:41Z jkoshy $
+# $Id: Makefile 3691 2019-02-23 23:34:04Z jkoshy $
TOP= ../../../..
TS_SRCS= ehdr.m4
-TS_YAML= ehdr
+TS_YAML= ehdr ehdr-malformed-1
.include "${TOP}/mk/elftoolchain.tet.mk"
diff --git a/test/libelf/tset/elf64_newehdr/Makefile b/test/libelf/tset/elf64_newehdr/Makefile
index 88ccf4d1791b..1e56f4113374 100644
--- a/test/libelf/tset/elf64_newehdr/Makefile
+++ b/test/libelf/tset/elf64_newehdr/Makefile
@@ -1,9 +1,10 @@
-# $Id: Makefile 1358 2011-01-08 05:40:41Z jkoshy $
+# $Id: Makefile 3702 2019-03-02 20:40:55Z jkoshy $
TOP= ../../../..
TS_SRCS= ehdr.m4
TS_DATA= ehdr.msb64 ehdr.lsb64 ehdr.msb32 ehdr.lsb32 \
+ ehdr-malformed-1.lsb64 ehdr-malformed-1.msb64 \
newehdr.lsb64 newehdr.msb64
.include "${TOP}/mk/elftoolchain.tet.mk"
diff --git a/test/libelf/tset/elf_begin/Makefile b/test/libelf/tset/elf_begin/Makefile
index d5c675cd0449..bdc1575f80c6 100644
--- a/test/libelf/tset/elf_begin/Makefile
+++ b/test/libelf/tset/elf_begin/Makefile
@@ -1,8 +1,9 @@
-# $Id: Makefile 2933 2013-03-30 01:33:02Z jkoshy $
+# $Id: Makefile 3704 2019-03-02 20:41:12Z jkoshy $
TOP= ../../../..
TS_SRCS= begin.m4
+TS_FILES= entry-too-large.ar
TS_DATA= check_elf.msb32 check_elf.lsb32 check_elf.msb64 \
check_elf.lsb64 a.ar a-bsd.ar a.o zero
CLEANFILES+= a.c
diff --git a/test/libelf/tset/elf_begin/begin.m4 b/test/libelf/tset/elf_begin/begin.m4
index 9a282eb3f746..16ac34e66826 100644
--- a/test/libelf/tset/elf_begin/begin.m4
+++ b/test/libelf/tset/elf_begin/begin.m4
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: begin.m4 2933 2013-03-30 01:33:02Z jkoshy $
+ * $Id: begin.m4 3706 2019-03-02 20:57:45Z jkoshy $
*/
#include <sys/stat.h>
@@ -634,3 +634,44 @@ tcArMemoryFdIgnored_$1(void)
ARFN(`BSD')
ARFN(`SVR4')
+
+/*
+ * Verify behavior with a corrupted header containing a too-large size.
+ */
+void
+tcArEntryTooLarge(void)
+{
+ Elf *ar_e, *e;
+ int error, fd, result;
+
+ result = TET_UNRESOLVED;
+ ar_e = NULL;
+ e = NULL;
+
+ TP_ANNOUNCE("elf_begin() returns ELF_E_ARCHIVE for too-large archive "
+ "entries.");
+
+ TP_SET_VERSION();
+
+ _TS_OPEN_FILE(ar_e, "entry-too-large.ar", ELF_C_READ, fd, goto done;);
+
+ if ((e = elf_begin(fd, ELF_C_READ, ar_e)) != NULL) {
+ TP_FAIL("elf_begin() succeeded.");
+ goto done;
+ }
+
+ error = elf_errno();
+ if (error != ELF_E_ARCHIVE) {
+ TP_FAIL("unexpected error %d", error);
+ goto done;
+ }
+
+ result = TET_PASS;
+
+done:
+ if (e)
+ (void) elf_end(e);
+ if (ar_e)
+ (void) elf_end(ar_e);
+ tet_result(result);
+}
diff --git a/test/libelf/tset/elf_begin/entry-too-large.ar b/test/libelf/tset/elf_begin/entry-too-large.ar
new file mode 100644
index 000000000000..5cab1486306c
--- /dev/null
+++ b/test/libelf/tset/elf_begin/entry-too-large.ar
@@ -0,0 +1,3 @@
+!<arch>
+a1.c/ 1551379738 1000 1000 100644 9 `
+1234567
diff --git a/test/libelf/tset/elf_getdata/getdata.m4 b/test/libelf/tset/elf_getdata/getdata.m4
index 40afc8a4ec30..332f81bcebe3 100644
--- a/test/libelf/tset/elf_getdata/getdata.m4
+++ b/test/libelf/tset/elf_getdata/getdata.m4
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: getdata.m4 2090 2011-10-27 08:07:39Z jkoshy $
+ * $Id: getdata.m4 3695 2019-02-25 18:55:07Z jkoshy $
*/
#include <libelf.h>
@@ -68,6 +68,36 @@ findscn(Elf *e, const char *name)
return (NULL);
}
+/*
+ * Check the contents of an Elf_Data descriptor.
+ *
+ * The return value from this helper is as follows:
+ *
+ * 0 - the descriptor matched the specified content.
+ * -1 - the descriptor size had a mismatch.
+ * >0 - the content of the descriptor did not match. The returned value
+ * is the index of the first byte that differs.
+ */
+static int
+match_content(Elf_Data *ed, size_t nbytes, const char *content)
+{
+ int n;
+ const char *buf;
+
+ if (ed->d_size != nbytes)
+ return (-1);
+
+ buf = (const char *) ed->d_buf;
+ for (n = 0; n < nbytes; n++) {
+ if (*buf != *content)
+ return (n);
+ buf++;
+ content++;
+ }
+
+ return (0);
+}
+
define(`ZEROSECTION',".zerosection")
undefine(`FN')
define(`FN',`
@@ -106,6 +136,11 @@ tcZeroSection$1$2(void)
goto done;
}
+ if ((ed = elf_getdata(scn, ed)) != NULL) {
+ TP_FAIL("Extra data descriptor in section.");
+ goto done;
+ }
+
result = TET_PASS;
done:
@@ -139,16 +174,17 @@ define(`_FN',`
void
tcNonZeroSection$1$2(void)
{
- Elf *e;
int error, fd, result;
- const size_t strsectionsize = sizeof stringsection;
- size_t n, shstrndx;
+ int match_error;
+ size_t shstrndx;
const char *buf;
Elf_Scn *scn;
Elf_Data *ed;
+ Elf *e;
- e = NULL;
fd = -1;
+ e = NULL;
+ scn = NULL;
result = TET_UNRESOLVED;
TP_ANNOUNCE("a data descriptor for a non-zero sized section "
@@ -170,19 +206,22 @@ tcNonZeroSection$1$2(void)
goto done;
}
- if (ed->d_size != strsectionsize) {
+ match_error = match_content(ed, sizeof(stringsection),
+ stringsection);
+ if (match_error == -1) {
TP_FAIL("Illegal values returned: d_size %d != expected %d",
- (int) ed->d_size, strsectionsize);
+ (int) ed->d_size, sizeof(stringsection));
goto done;
- }
-
- if (memcmp(stringsection, ed->d_buf, strsectionsize) != 0) {
+ } else if (match_error > 0) {
buf = (const char *) ed->d_buf;
- for (n = 0; n < strsectionsize; n++)
- if (buf[n] != stringsection[n])
- break;
TP_FAIL("String mismatch: buf[%d] \"%c\" != \"%c\"",
- n, buf[n], stringsection[n]);
+ match_error, buf[match_error],
+ stringsection[match_error]);
+ goto done;
+ }
+
+ if ((ed = elf_getdata(scn, ed)) != NULL) {
+ TP_FAIL("Extra data descriptor in section.");
goto done;
}
@@ -201,3 +240,112 @@ _FN(lsb,32)
_FN(lsb,64)
_FN(msb,32)
_FN(msb,64)
+
+static const char new_content[] = {
+changequote({,})
+ 'n', 'e', 'w', ' ', 'c', 'o', 'n', 't', 'e', 'n', 't', '\0'
+changequote
+};
+
+/*
+ * Verify that a section with multiple Elf_Data segments is handled correctly.
+ */
+undefine(`_FN')
+define(`_FN',`
+void
+tcDataTraversal$1$2(void)
+{
+ Elf *e;
+ Elf_Scn *scn;
+ Elf_Data *ed;
+ size_t shstrndx;
+ int error, fd, match_error, result;
+
+ e = NULL;
+ fd = -1;
+ result = TET_UNRESOLVED;
+
+ TP_ANNOUNCE("multiple Elf_Data segments can be traversed.");
+ _TS_OPEN_FILE(e, "zerosection.$1$2", ELF_C_READ, fd, goto done;);
+
+ if (elf_getshdrstrndx(e, &shstrndx) != 0 ||
+ (scn = elf_getscn(e, shstrndx)) == NULL) {
+ TP_UNRESOLVED("Cannot find the string table");
+ goto done;
+ }
+
+ /*
+ * Add new data to the string section.
+ */
+ if ((ed = elf_newdata(scn)) == NULL) {
+ TP_UNRESOLVED("Cannot allocate new data.");
+ goto done;
+ }
+
+ ed->d_buf = (char *) new_content;
+ ed->d_size = sizeof(new_content);
+
+ /*
+ * Rescan the descriptor list for the section.
+ */
+ ed = NULL;
+ if ((ed = elf_getdata(scn, ed)) == NULL) {
+ error = elf_errno();
+ TP_FAIL("elf_getdata failed %d \"%s\"", error,
+ elf_errmsg(error));
+ goto done;
+ }
+
+ match_error = match_content(ed, sizeof(stringsection),
+ stringsection);
+ if (match_error == -1) {
+ TP_FAIL("Unexpected size of first descriptor: "
+ "d_size %d != expected %d", (int) ed->d_size,
+ sizeof(stringsection));
+ goto done;
+ } else if (match_error > 0) {
+ TP_FAIL("String content mismatch for data descriptor 1.");
+ goto done;
+ }
+
+ if ((ed = elf_getdata(scn, ed)) == NULL) {
+ error = elf_errno();
+ TP_FAIL("Missing second data section: %d \"%s\"", error,
+ elf_errmsg(error));
+ goto done;
+ }
+
+ match_error = match_content(ed, sizeof(new_content),
+ new_content);
+ if (match_error == -1) {
+ TP_FAIL("Unexpected size of second descriptor: "
+ "d_size %d != expected %d", (int) ed->d_size,
+ sizeof(new_content));
+ goto done;
+ } else if (match_error > 0) {
+ TP_FAIL("String content mismatch for data descriptor 2.");
+ goto done;
+ }
+
+ /*
+ * There should be no other Elf_Data descriptors.
+ */
+ if ((ed = elf_getdata(scn, ed)) != NULL) {
+ TP_FAIL("Too many Elf_Data descriptors for section.");
+ goto done;
+ }
+
+ result = TET_PASS;
+
+done:
+ if (e)
+ elf_end(e);
+ if (fd != -1)
+ (void) close(fd);
+ tet_result(result);
+}')
+
+_FN(lsb,32)
+_FN(lsb,64)
+_FN(msb,32)
+_FN(msb,64)
diff --git a/test/libelf/tset/elf_rand/Makefile b/test/libelf/tset/elf_rand/Makefile
new file mode 100644
index 000000000000..1b17ff29796c
--- /dev/null
+++ b/test/libelf/tset/elf_rand/Makefile
@@ -0,0 +1,18 @@
+# $Id$
+
+TOP= ../../../..
+
+TS_SRCS= rand.m4
+TS_DATA= a.ar s1 s2
+TS_FILES= empty-file.ar missing-file.ar
+
+s1: .SILENT
+ echo 'This is s1.' > ${.TARGET}
+s2: .SILENT
+ echo 's2.' > ${.TARGET}
+
+a.ar: s1 s2 .SILENT
+ rm -f ${.TARGET}
+ ${AR} crv ${.TARGET} s1 s2 > /dev/null
+
+.include "${TOP}/mk/elftoolchain.tet.mk"
diff --git a/test/libelf/tset/elf_rand/empty-file.ar b/test/libelf/tset/elf_rand/empty-file.ar
new file mode 100644
index 000000000000..f7039eda3a06
--- /dev/null
+++ b/test/libelf/tset/elf_rand/empty-file.ar
@@ -0,0 +1,2 @@
+!<arch>
+e1/ 0 0 0 644 0 `
diff --git a/test/libelf/tset/elf_rand/missing-file.ar b/test/libelf/tset/elf_rand/missing-file.ar
new file mode 100644
index 000000000000..d62c803db28b
--- /dev/null
+++ b/test/libelf/tset/elf_rand/missing-file.ar
@@ -0,0 +1,2 @@
+!<arch>
+e1/ 0 0 0 644 42 `
diff --git a/test/libelf/tset/elf_rand/rand.m4 b/test/libelf/tset/elf_rand/rand.m4
new file mode 100644
index 000000000000..bdcf436456b5
--- /dev/null
+++ b/test/libelf/tset/elf_rand/rand.m4
@@ -0,0 +1,415 @@
+/*-
+ * Copyright (c) 2019 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <ar.h>
+#include <libelf.h>
+#include <limits.h>
+#include <unistd.h>
+
+#include "elfts.h"
+#include "tet_api.h"
+
+IC_REQUIRES_VERSION_INIT();
+
+include(`elfts.m4')
+
+/*
+ * The following definitions should match those in `./Makefile'.
+ */
+define(`TP_ARFILE',`"a.ar"')
+define(`TP_NONARCHIVE', `"s1"')
+
+/*
+ * The use of an offset less than SARMAG should fail.
+ */
+void
+tcSeekBelowSarmag(void)
+{
+ Elf *ar;
+ off_t offset;
+ int error, fd, result;
+
+ fd = -1;
+ ar = NULL;
+ result = TET_UNRESOLVED;
+
+ TP_CHECK_INITIALIZATION();
+ TP_ANNOUNCE("elf_rand() fails for an offset less than SARMAG");
+
+ TS_OPEN_FILE(ar, TP_ARFILE, ELF_C_READ, fd);
+
+ result = TET_PASS;
+
+ if ((offset = elf_rand(ar, 1)) != 0) {
+ TP_FAIL("elf_rand() succeeded with offset=%lld",
+ (unsigned long long) offset);
+ } else if ((error = elf_errno()) != ELF_E_ARGUMENT) {
+ TP_FAIL("unexpected error=%d \"%s\"", error,
+ elf_errmsg(error));
+ }
+
+ (void) elf_end(ar);
+ (void) close(fd);
+
+ tet_result(result);
+}
+
+/*
+ * The use of an offset greater than the largest valid file offset
+ * should fail.
+ */
+void
+tcSeekMoreThanFileSize(void)
+{
+ Elf *ar;
+ off_t offset;
+ struct stat sb;
+ int error, fd, result;
+
+ result = TET_UNRESOLVED;
+ ar = NULL;
+ fd = -1;
+
+ TP_CHECK_INITIALIZATION();
+ TP_ANNOUNCE("elf_rand() fails with a too-large offset");
+
+ TS_OPEN_FILE(ar, TP_ARFILE, ELF_C_READ, fd);
+
+ /* Get the file size of the archive. */
+ if (fstat(fd, &sb) < 0) {
+ TP_UNRESOLVED("cannot determine the size of \"%s\"",
+ TP_ARFILE);
+ goto done;
+ }
+
+ result = TET_PASS;
+
+ if ((offset = elf_rand(ar, sb.st_size)) != 0) {
+ TP_FAIL("elf_rand() succeeded with offset=%lld",
+ (unsigned long long) offset);
+ } else if ((error = elf_errno()) != ELF_E_ARGUMENT) {
+ TP_FAIL("unexpected error=%d \"%s\"", error,
+ elf_errmsg(error));
+ }
+
+done:
+ if (ar)
+ (void) elf_end(ar);
+ if (fd != -1)
+ (void) close(fd);
+
+ tet_result(result);
+}
+
+/*
+ * An offset with value SARMAG is accepted.
+ */
+void
+tcOffsetEqualsSARMAG(void)
+{
+ Elf *ar;
+ off_t offset;
+ int fd, result;
+
+ fd = -1;
+ ar = NULL;
+ result = TET_UNRESOLVED;
+
+ TP_CHECK_INITIALIZATION();
+ TP_ANNOUNCE("elf_rand(SARMAG) succeeds.");
+
+ TS_OPEN_FILE(ar, TP_ARFILE, ELF_C_READ, fd);
+
+ if ((offset = elf_rand(ar, SARMAG)) != SARMAG) {
+ TP_FAIL("unexpected offset: %lld",
+ (long long) offset);
+ goto done;
+ }
+
+ result = TET_PASS;
+
+done:
+ if (ar)
+ (void) elf_end(ar);
+ if (fd != -1)
+ (void) close(fd);
+
+ tet_result(result);
+}
+
+/*
+ * Invoking elf_rand() on a non-archive should fail.
+ */
+void
+tcOnNonArchive(void)
+{
+ Elf *e;
+ off_t offset;
+ int error, fd, result;
+
+ fd = -1;
+ e = NULL;
+ result = TET_UNRESOLVED;
+
+ TP_CHECK_INITIALIZATION();
+ TP_ANNOUNCE("elf_rand(non-archive) fails.");
+
+ TS_OPEN_FILE(e, TP_NONARCHIVE, ELF_C_READ, fd);
+
+ if ((offset = elf_rand(e, SARMAG)) != 0 ||
+ (error = elf_errno()) != ELF_E_ARGUMENT) {
+ TP_FAIL("unexpected offset=%lld",
+ (long long) offset);
+ goto done;
+ }
+
+ result = TET_PASS;
+
+done:
+ if (e)
+ (void) elf_end(e);
+ if (fd != -1)
+ (void) close(fd);
+
+ tet_result(result);
+}
+
+/*
+ * Use an offset value that could cause an overflow.
+ */
+void
+tcOffsetOverflow(void)
+{
+ Elf *ar;
+ off_t offset;
+ uint64_t max_offset;
+ int error, fd, result;
+
+ fd = -1;
+ ar = NULL;
+ result = TET_UNRESOLVED;
+
+ /* A even offset that is close to overflowing. */
+ max_offset = (1ULL << (sizeof(off_t) * CHAR_BIT - 1)) - 2;
+
+ TP_CHECK_INITIALIZATION();
+ TP_ANNOUNCE("offset close to overflowing an off_t");
+
+ TS_OPEN_FILE(ar, TP_ARFILE, ELF_C_READ, fd);
+
+ if ((offset = elf_rand(ar, (off_t) max_offset)) != 0) {
+ TP_FAIL("unexpected success, offset=%lld",
+ (long long) offset);
+ goto done;
+ }
+
+ result = TET_PASS;
+
+done:
+ if (ar)
+ (void) elf_end(ar);
+ if (fd != -1)
+ (void) close(fd);
+
+ tet_result(result);
+}
+
+/*
+ * Setting the offset to a value that does not correspond to an ar header
+ * should fail.
+ */
+void
+tcOffsetNotCorrespondingToAnArchiveHeader(void)
+{
+ Elf *ar;
+ off_t offset;
+ int error, fd, result;
+
+ fd = -1;
+ ar = NULL;
+ result = TET_UNRESOLVED;
+
+ TP_CHECK_INITIALIZATION();
+ TP_ANNOUNCE("elf_rand(non-header-offset) should fail.");
+
+ TS_OPEN_FILE(ar, TP_ARFILE, ELF_C_READ, fd);
+
+ if ((offset = elf_rand(ar, SARMAG+2)) != 0) {
+ TP_FAIL("unexpected success, offset=%lld",
+ (long long) offset);
+ goto done;
+ } else if ((error = elf_errno()) != ELF_E_ARCHIVE) {
+ TP_FAIL("unexpected error=%d \"%s\"", error,
+ elf_errmsg(error));
+ goto done;
+ }
+
+ result = TET_PASS;
+
+done:
+ if (ar)
+ (void) elf_end(ar);
+ if (fd != -1)
+ (void) close(fd);
+
+ tet_result(result);
+}
+
+/*
+ * Odd values of offsets are not legal.
+ */
+void
+tcOddOffset(void)
+{
+ Elf *ar;
+ off_t offset;
+ int error, fd, result;
+
+ fd = -1;
+ ar = NULL;
+ result = TET_UNRESOLVED;
+
+ TP_CHECK_INITIALIZATION();
+ TP_ANNOUNCE("elf_rand(odd-offset-value) should fail.");
+
+ TS_OPEN_FILE(ar, TP_ARFILE, ELF_C_READ, fd);
+
+ if ((offset = elf_rand(ar, SARMAG+1)) != 0) {
+ TP_FAIL("unexpected success, offset=%lld",
+ (long long) offset);
+ goto done;
+ } else if ((error = elf_errno()) != ELF_E_ARGUMENT) {
+ TP_FAIL("unexpected error=%d \"%s\"", error,
+ elf_errmsg(error));
+ goto done;
+ }
+
+ result = TET_PASS;
+
+done:
+ if (ar)
+ (void) elf_end(ar);
+ if (fd != -1)
+ (void) close(fd);
+
+ tet_result(result);
+}
+
+/*
+ * Negative offset values are not legal.
+ */
+void
+tcNegativeOffset(void)
+{
+ Elf *ar;
+ off_t offset;
+ int error, fd, result;
+
+ fd = -1;
+ ar = NULL;
+ result = TET_UNRESOLVED;
+
+ TP_CHECK_INITIALIZATION();
+ TP_ANNOUNCE("elf_rand(odd-offset-value) should fail.");
+
+ TS_OPEN_FILE(ar, TP_ARFILE, ELF_C_READ, fd);
+
+ if ((offset = elf_rand(ar, -SARMAG)) != 0) {
+ TP_FAIL("unexpected success, offset=%lld",
+ (long long) offset);
+ goto done;
+ } else if ((error = elf_errno()) != ELF_E_ARGUMENT) {
+ TP_FAIL("unexpected error=%d \"%s\"", error,
+ elf_errmsg(error));
+ goto done;
+ }
+
+ result = TET_PASS;
+
+done:
+ if (ar)
+ (void) elf_end(ar);
+ if (fd != -1)
+ (void) close(fd);
+
+ tet_result(result);
+}
+
+
+/* These offsets correspond to archive TP_ARFILE. */
+static off_t valid_offsets[] = {
+ SARMAG, /* File 's1'. */
+ 80 /* File 's2'. */
+};
+
+static const int number_of_offsets =
+ sizeof(valid_offsets) / sizeof(valid_offsets[0]);
+
+/*
+ * Valid offsets should be usable.
+ */
+void
+tcValidOffsets(void)
+{
+ Elf *ar;
+ off_t offset;
+ int i, error, fd, result;
+
+ fd = -1;
+ ar = NULL;
+ result = TET_UNRESOLVED;
+
+ TP_CHECK_INITIALIZATION();
+ TP_ANNOUNCE("elf_rand(valid-offsets) succeeds.");
+
+ TS_OPEN_FILE(ar, TP_ARFILE, ELF_C_READ, fd);
+
+ for (i = 0; i < number_of_offsets; i++) {
+ if ((offset = elf_rand(ar, valid_offsets[i])) !=
+ valid_offsets[i]) {
+ error = elf_errno();
+ TP_FAIL("failed to seek to offset %lld, error=%d "
+ "\"%s\"", (long long) offset, error,
+ elf_errmsg(error));
+ goto done;
+ }
+ }
+
+ result = TET_PASS;
+
+done:
+ if (ar)
+ (void) elf_end(ar);
+ if (fd != -1)
+ (void) close(fd);
+
+ tet_result(result);
+}