On Fri, Mar 19, 2004 at 01:04:54AM +0100, Jakub Bogusz wrote:
> On Thu, Mar 18, 2004 at 11:14:44PM +0100, Artur Frysiak wrote:
> > Witam.
> > Zabieram się za przygotowanie nowego snapa rpma ponieważ posiada on
> > wsparcie do wbudowanego języka skryptowego lua.
> > Korzyści płynące z lua to możliwość pisania skryptów %pre/%post które
> > nie będą wymagały sh. Może się to okazać bardzo przydatne w pakietach
> > typu FHS, setup, glibc itp.
> > 
> > Cały eksperyment zostanie przeprowadzony na branchu DEVEL.
> 
> Popatrzysz przy okazji, czy nie ma jakichś poprawek w readelf?
> W poprzednim snapie były błędy, ale po uaktualnieniu (z nowszego file)
> coś się sypie na amd64 i nie mam jak zdiagnozować bez dostępu do
> maszyny.

revision 1.4
date: 2004/03/16 17:13:25;  author: jbj;  state: Exp;  lines: +37 -14
- fix: grrr, skip notes on non-i386 entirely.
----------------------------
revision 1.3
date: 2004/03/13 13:34:45;  author: jbj;  state: Exp;  lines: +30 -31
- fix: handle elf64 note sections correctly.

i podobne zmiany w branczach rpm-4_3 oraz rpm-4_2.
Łatka w załączniku.

Pozdrawiam
-- 
Artur Frysiak
http://www.pld-linux.org/
Index: file/src/readelf.c
===================================================================
RCS file: /cvs/devel/rpm/file/src/readelf.c,v
retrieving revision 1.2
retrieving revision 1.4
diff -u -r1.2 -r1.4
--- file/src/readelf.c  15 Apr 2003 15:19:30 -0000      1.2
+++ file/src/readelf.c  16 Mar 2004 17:13:25 -0000      1.4
@@ -88,6 +88,7 @@
 #define shs_type       (fm->cls == ELFCLASS32          \
                         ? getu32(fm, sh32.sh_type)     \
                         : getu32(fm, sh64.sh_type))
+
 #define ph_addr                (fm->cls == ELFCLASS32          \
                         ? (void *) &ph32               \
                         : (void *) &ph64)
@@ -103,9 +104,10 @@
 #define ph_align       (fm->cls == ELFCLASS32          \
                         ? (ph32.p_align ? getu32(fm, ph32.p_align) : 4) \
                         : (ph64.p_align ? getu64(fm, ph64.p_align) : 4))
-#define nh_size                (fm->cls == ELFCLASS32          \
-                        ? sizeof *nh32                 \
-                        : sizeof *nh64)
+#define ph_filesz      (fm->cls == ELFCLASS32          \
+                        ? getu32(fm, ph32.p_filesz)    \
+                        : getu64(fm, ph64.p_filesz))
+
 #define nh_type                (fm->cls == ELFCLASS32          \
                         ? getu32(fm, nh32->n_type)     \
                         : getu32(fm, nh64->n_type))
@@ -170,8 +172,11 @@
        char *linking_style = "statically";
        char *shared_libraries = "";
        char nbuf[BUFSIZ];
-       int bufsize;
-       size_t offset, nameoffset;
+       int nb;
+       size_t nbufsize, offset, end, noff, doff;
+       size_t align = (fm->cls == ELFCLASS32 ? 4 : 8);
+#define ALIGNED_LEN(len) (((len) + align - 1) & ~(align - 1))
+       int printed;
 
        if (size != ph_size) {
                error(EXIT_FAILURE, 0, "corrupted program header size.\n");
@@ -184,11 +189,19 @@
        }
 
        for ( ; num; num--) {
-               if (read(fm->fd, ph_addr, size) == -1) {
+               /* Read the program header data. */
+               nb = read(fm->fd, ph_addr, size);
+               if (nb == -1) {
                        error(EXIT_FAILURE, 0, "read failed (%s).\n", strerror(errno));
                        /[EMAIL PROTECTED]@*/
                }
 
+               /* XXX Elf64 notes cannot be read, so don't attempt for now. */
+#if !defined(__i386__)
+               if (ph_type == PT_NOTE) 
+                       break;          
+#endif
+
                switch (ph_type) {
                case PT_DYNAMIC:
                        linking_style = "dynamically";
@@ -205,50 +218,56 @@
                                error(EXIT_FAILURE, 0, "lseek failed (%s).\n", 
strerror(errno));
                                /[EMAIL PROTECTED]@*/
                        }
-                       bufsize = read(fm->fd, nbuf, sizeof(nbuf));
-                       if (bufsize == -1) {
+
+                       /* XXX Read only the notes section. */
+                       nbufsize = (ph_filesz < sizeof(nbuf)
+                                       ? ph_filesz : sizeof(nbuf));
+                       nb = read(fm->fd, nbuf, nbufsize);
+                       if (nb == -1) {
                                error(EXIT_FAILURE, 0, ": " "read failed (%s).\n",
                                    strerror(errno));
                                /[EMAIL PROTECTED]@*/
                        }
                        offset = 0;
+                       printed = 0;
                        for (;;) {
-                               if (offset >= bufsize)
+                               end = offset + 12;
+                               if (end >= nb)
                                        /[EMAIL PROTECTED]@*/ break;
+
                                if (fm->cls == ELFCLASS32)
                                        nh32 = (Elf32_Nhdr *)&nbuf[offset];
                                else
                                        nh64 = (Elf64_Nhdr *)&nbuf[offset];
-                               offset += nh_size;
-       
-                               if (offset + nh_namesz >= bufsize) {
-                                       /*
-                                        * We're past the end of the buffer.
-                                        */
-                                       /[EMAIL PROTECTED]@*/ break;
-                               }
 
-                               nameoffset = offset;
-                               offset += nh_namesz;
-                               offset = ((offset+ph_align-1)/ph_align)*ph_align;
+                               offset = end;   /* skip note header. */
 
-                               if ((nh_namesz == 0) && (nh_descsz == 0)) {
-                                       /*
-                                        * We're out of note headers.
-                                        */
+                               /* XXX Avoid notes that are not 1-16 bytes */
+                               if (nh_namesz <= 0 || nh_descsz <= 0)
+                                       break;
+                               if (nh_namesz  > 16 || nh_descsz > 16)
+                                       break;
+
+                               end = offset    + ALIGNED_LEN (nh_namesz)
+                                               + ALIGNED_LEN (nh_descsz);
+                               if (end > nb)
                                        /[EMAIL PROTECTED]@*/ break;
-                               }
 
-                               if (offset + nh_descsz >= bufsize)
-                                       /[EMAIL PROTECTED]@*/ break;
+                               noff = offset;
+                               doff = ALIGNED_LEN(offset + nh_namesz);
+                               offset = end;
+
+                               if (printed)
+                                       continue;
 
                                if (nh_namesz == 4 &&
-                                   strcmp(&nbuf[nameoffset], "GNU") == 0 &&
+                                   strcmp(&nbuf[noff], "GNU") == 0 &&
                                    nh_type == NT_GNU_VERSION &&
                                    nh_descsz == 16) {
                                        uint32_t *desc =
-                                           (uint32_t *)&nbuf[offset];
+                                           (uint32_t *)&nbuf[doff];
 
+                                       if (!printed)
                                        file_printf(fm, ", for GNU/");
                                        switch (getu32(fm, desc[0])) {
                                        case GNU_OS_LINUX:
@@ -268,10 +287,11 @@
                                            getu32(fm, desc[1]),
                                            getu32(fm, desc[2]),
                                            getu32(fm, desc[3]));
+                                       printed = 1;
                                }
 
                                if (nh_namesz == 7 &&
-                                   strcmp(&nbuf[nameoffset], "NetBSD") == 0 &&
+                                   strcmp(&nbuf[noff], "NetBSD") == 0 &&
                                    nh_type == NT_NETBSD_VERSION &&
                                    nh_descsz == 4) {
                                        file_printf(fm, ", for NetBSD");
@@ -279,14 +299,15 @@
                                         * Version number is stuck at 199905,
                                         * and hence is basically content-free.
                                         */
+                                       printed = 1;
                                }
 
                                if (nh_namesz == 8 &&
-                                   strcmp(&nbuf[nameoffset], "FreeBSD") == 0 &&
+                                   strcmp(&nbuf[noff], "FreeBSD") == 0 &&
                                    nh_type == NT_FREEBSD_VERSION &&
                                    nh_descsz == 4) {
                                        uint32_t desc = getu32(fm,
-                                           *(uint32_t *)&nbuf[offset]);
+                                           *(uint32_t *)&nbuf[doff]);
                                        file_printf(fm, ", for FreeBSD");
                                        /*
                                         * Contents is __FreeBSD_version,
@@ -303,14 +324,16 @@
                                        if (desc / 1000 % 10 > 0)
                                                file_printf(fm, ".%d",
                                                    desc / 1000 % 10);
+                                       printed = 1;
                                }
 
                                if (nh_namesz == 8 &&
-                                   strcmp(&nbuf[nameoffset], "OpenBSD") == 0 &&
+                                   strcmp(&nbuf[noff], "OpenBSD") == 0 &&
                                    nh_type == NT_OPENBSD_VERSION &&
                                    nh_descsz == 4) {
                                        file_printf(fm, ", for OpenBSD");
                                        /* Content of note is always 0 */
+                                       printed = 1;
                                }
                        }
                        if ((lseek(fm->fd, ph_offset + offset, SEEK_SET)) == -1) {
@@ -389,7 +412,7 @@
        unsigned char c;
        int i, j;
        char nbuf[BUFSIZ];
-       int bufsize;
+       int nb;
        int os_style = -1;
 
        if (size != ph_size) {
@@ -421,26 +444,26 @@
                        error(EXIT_FAILURE, 0, "lseek failed (%s).\n", 
strerror(errno));
                        /[EMAIL PROTECTED]@*/
                }
-               bufsize = read(fm->fd, nbuf, BUFSIZ);
-               if (bufsize == -1) {
+               nb = read(fm->fd, nbuf, BUFSIZ);
+               if (nb == -1) {
                        error(EXIT_FAILURE, 0, ": " "read failed (%s).\n", 
strerror(errno));
                        /[EMAIL PROTECTED]@*/
                }
                offset = 0;
                for (;;) {
-                       if (offset >= bufsize)
+                       if (offset >= nb)
                                /[EMAIL PROTECTED]@*/ break;
                        if (fm->cls == ELFCLASS32)
                                nh32 = (Elf32_Nhdr *)&nbuf[offset];
                        else
                                nh64 = (Elf64_Nhdr *)&nbuf[offset];
-                       offset += nh_size;
+                       offset += 12;
 
                        /*
                         * Check whether this note has the name "CORE" or
                         * "FreeBSD", or "NetBSD-CORE".
                         */
-                       if (offset + nh_namesz >= bufsize) {
+                       if (offset + nh_namesz >= nb) {
                                /*
                                 * We're past the end of the buffer.
                                 */
@@ -529,7 +552,7 @@
                                                 * the end of the buffer; if
                                                 * we are, just give up.
                                                 */
-                                               if (noffset >= bufsize)
+                                               if (noffset >= nb)
                                                        goto tryanother;
 
                                                /*
@@ -615,7 +638,6 @@
            || fm->buf[EI_MAG2] != ELFMAG2 || fm->buf[EI_MAG3] != ELFMAG3)
            return;
 
-
        fm->cls = fm->buf[EI_CLASS];
 
        if (fm->cls == ELFCLASS32) {

_______________________________________________________
z�ota zasada - kto si� nie zna, niech si� nie wypowiada

Odpowiedź listem elektroniczym