static int nsis_headers(struct nsis_st *n, cli_ctx *ctx) { char buf[28]; struct stat st; uint32_t pos; int i; uint8_t comps[] = {0, 0, 0, 0}, trunc = 0; if (fstat(n->ifd, &st)==-1 || lseek(n->ifd, n->off, SEEK_SET)==-1 || cli_readn(n->ifd, buf, 28) != 28) return CL_EIO; n->hsz = (uint32_t)cli_readint32(buf+0x14); n->asz = (uint32_t)cli_readint32(buf+0x18); cli_dbgmsg("NSIS: Header info - Flags=%x, Header size=%x, Archive size=%x\n", cli_readint32(buf), n->hsz, n->asz); if (st.st_size - n->off < (off_t) n->asz) { cli_dbgmsg("NSIS: Possibly truncated file\n"); n->asz = st.st_size - n->off; trunc++; } else if (st.st_size - n->off != (off_t) n->asz) { cli_dbgmsg("NSIS: Overlays found\n"); } n->asz -= 0x1c; /* Guess if solid */ for (i=0, pos=0;pos < n->asz-4;i++) { int32_t nextsz; if (cli_readn(n->ifd, buf+4, 4)!=4) return CL_EIO; nextsz=cli_readint32(buf+4); if (!i) n->comp = nsis_detcomp(buf+4); if (nextsz&0x80000000) { nextsz&=~0x80000000; if (cli_readn(n->ifd, buf+4, 4)!=4) return CL_EIO; comps[nsis_detcomp(buf+4)]++; nextsz-=4; pos+=4; } if ((pos+=4+nextsz) > n->asz) { n->solid = 1; break; } if (lseek(n->ifd, nextsz, SEEK_CUR)==-1) return CL_EIO; } if (trunc && i>=2) n->solid=0; cli_dbgmsg("NSIS: solid compression%s detected\n", (n->solid)?"":" not"); /* Guess the compression method */ if (!n->solid) { cli_dbgmsg("NSIS: bzip2 %u - lzma %u - zlib %u\n", comps[1], comps[2], comps[3]); n->comp = (comps[1]<comps[2]) ? (comps[2]<comps[3] ? COMP_ZLIB : COMP_LZMA) : (comps[1]<comps[3] ? COMP_ZLIB : COMP_BZIP2); } if (lseek(n->ifd, n->off+0x1c, SEEK_SET)==-1) return CL_EIO; return nsis_unpack_next(n, ctx); }
static int cli_nsis_unpack(struct nsis_st *n, cli_ctx *ctx) { return (n->fno) ? nsis_unpack_next(n, ctx) : nsis_headers(n, ctx); }
static int nsis_headers(struct nsis_st *n, cli_ctx *ctx) { const char *buf; uint32_t pos; int i; uint8_t comps[] = {0, 0, 0, 0}, trunc = 0; if (!(buf = fmap_need_off_once(n->map, n->off, 0x1c))) return CL_EREAD; n->hsz = (uint32_t)cli_readint32(buf+0x14); n->asz = (uint32_t)cli_readint32(buf+0x18); n->fullsz = n->map->len; cli_dbgmsg("NSIS: Header info - Flags=%x, Header size=%x, Archive size=%x\n", cli_readint32(buf), n->hsz, n->asz); if (n->fullsz - n->off < (off_t) n->asz) { cli_dbgmsg("NSIS: Possibly truncated file\n"); n->asz = n->fullsz - n->off; trunc++; } else if (n->fullsz - n->off != (off_t) n->asz) { cli_dbgmsg("NSIS: Overlays found\n"); } n->asz -= 0x1c; buf += 0x1c; /* Guess if solid */ for (i=0, pos=0;pos < n->asz-4;i++) { int32_t nextsz; if (!(buf = fmap_need_ptr_once(n->map, (void *)buf, 4))) return CL_EREAD; nextsz=cli_readint32(buf); if (!i) n->comp = nsis_detcomp(buf); buf += 4; if (nextsz&0x80000000) { nextsz&=~0x80000000; if (!(buf = fmap_need_ptr_once(n->map, (void *)buf, 4))) return CL_EREAD; comps[nsis_detcomp(buf)]++; nextsz-=4; pos+=4; buf+=4; } if ((pos+=4+nextsz) > n->asz) { n->solid = 1; break; } buf += nextsz; } if (trunc && i>=2) n->solid=0; cli_dbgmsg("NSIS: solid compression%s detected\n", (n->solid)?"":" not"); /* Guess the compression method */ if (!n->solid) { cli_dbgmsg("NSIS: bzip2 %u - lzma %u - zlib %u\n", comps[1], comps[2], comps[3]); n->comp = (comps[1]<comps[2]) ? (comps[2]<comps[3] ? COMP_ZLIB : COMP_LZMA) : (comps[1]<comps[3] ? COMP_ZLIB : COMP_BZIP2); } n->curpos = n->off+0x1c; return nsis_unpack_next(n, ctx); }