VirtualBox

儲存庫 vbox 的更動 50139


忽略:
時間撮記:
2014-1-21 下午01:14:05 (11 年 以前)
作者:
vboxsync
訊息:

tar.cpp: Fixed wrong checksum calculation (should be unsigned) and verification (must check both unsigned and signed checksums for hysterical raisins).

檔案:
修改 1 筆資料

圖例:

未更動
新增
刪除
  • trunk/src/VBox/Runtime/common/zip/tar.cpp

    r49135 r50139  
    4141
    4242#include "internal/magics.h"
     43#include "tar.h"
    4344
    4445
     
    269270}
    270271
    271 DECLINLINE(int) rtTarCalcChkSum(PRTTARRECORD pRecord, uint32_t *pChkSum)
    272 {
    273     uint32_t check = 0;
    274     uint32_t zero = 0;
    275     for (size_t i = 0; i < sizeof(RTTARRECORD); ++i)
    276     {
    277         /* Calculate the sum of every byte from the header. The checksum field
    278          * itself is counted as all blanks. */
    279         if (   i <  RT_UOFFSETOF(RTTARRECORD, h.chksum)
    280             || i >= RT_UOFFSETOF(RTTARRECORD, h.linkflag))
    281             check += pRecord->d[i];
    282         else
    283             check += ' ';
    284         /* Additional check if all fields are zero, which indicate EOF. */
    285         zero += pRecord->d[i];
    286     }
    287 
    288     /* EOF? */
    289     if (!zero)
    290         return VERR_TAR_END_OF_FILE;
    291 
    292     *pChkSum = check;
    293     return VINF_SUCCESS;
     272/**
     273 * Calculates the TAR header checksums and detects if it's all zeros.
     274 *
     275 * @returns true if all zeros, false if not.
     276 * @param   pHdr                The header to checksum.
     277 * @param   pi32Unsigned        Where to store the checksum calculated using
     278 *                              unsigned chars.   This is the one POSIX
     279 *                              specifies.
     280 * @param   pi32Signed          Where to store the checksum calculated using
     281 *                              signed chars.
     282 *
     283 * @remarks The reason why we calculate the checksum as both signed and unsigned
     284 *          has to do with various the char C type being signed on some hosts
     285 *          and unsigned on others.
     286 *
     287 * @remarks Borrowed from tarvfs.cpp.
     288 */
     289static bool rtZipTarCalcChkSum(PCRTZIPTARHDR pHdr, int32_t *pi32Unsigned, int32_t *pi32Signed)
     290{
     291    int32_t i32Unsigned = 0;
     292    int32_t i32Signed   = 0;
     293
     294    /*
     295     * Sum up the entire header.
     296     */
     297    const char *pch    = (const char *)pHdr;
     298    const char *pchEnd = pch + sizeof(*pHdr);
     299    do
     300    {
     301        i32Unsigned += *(unsigned char *)pch;
     302        i32Signed   += *(signed   char *)pch;
     303    } while (++pch != pchEnd);
     304
     305    /*
     306     * Check if it's all zeros and replace the chksum field with spaces.
     307     */
     308    bool const fZeroHdr = i32Unsigned == 0;
     309
     310    pch    = pHdr->Common.chksum;
     311    pchEnd = pch + sizeof(pHdr->Common.chksum);
     312    do
     313    {
     314        i32Unsigned -= *(unsigned char *)pch;
     315        i32Signed   -= *(signed   char *)pch;
     316    } while (++pch != pchEnd);
     317
     318    i32Unsigned += (unsigned char)' ' * sizeof(pHdr->Common.chksum);
     319    i32Signed   += (signed   char)' ' * sizeof(pHdr->Common.chksum);
     320
     321    *pi32Unsigned = i32Unsigned;
     322    if (pi32Signed)
     323        *pi32Signed = i32Signed;
     324    return fZeroHdr;
    294325}
    295326
     
    306337
    307338    /* Check for data integrity & an EOF record */
    308     uint32_t check = 0;
    309     rc = rtTarCalcChkSum(pRecord, &check);
    310     /* EOF? */
    311     if (RT_FAILURE(rc))
    312         return rc;
     339    int32_t iUnsignedChksum, iSignedChksum;
     340    if (rtZipTarCalcChkSum((PCRTZIPTARHDR)pRecord, &iUnsignedChksum, &iSignedChksum))
     341        return VERR_TAR_END_OF_FILE;
    313342
    314343    /* Verify the checksum */
    315344    uint32_t sum;
    316345    rc = RTStrToUInt32Full(pRecord->h.chksum, 8, &sum);
    317     if (RT_SUCCESS(rc) && sum == check)
     346    if (   RT_SUCCESS(rc)
     347        && (   sum == (uint32_t)iSignedChksum
     348            || sum == (uint32_t)iUnsignedChksum) )
    318349    {
    319350        /* Make sure the strings are zero terminated. */
     
    351382
    352383    /* Create the checksum out of the new header */
    353     uint32_t uChkSum = 0;
    354     int rc = rtTarCalcChkSum(pRecord, &uChkSum);
    355     if (RT_FAILURE(rc))
    356         return rc;
     384    int32_t iUnsignedChksum, iSignedChksum;
     385    if (rtZipTarCalcChkSum((PCRTZIPTARHDR)pRecord, &iUnsignedChksum, &iSignedChksum))
     386        return VERR_TAR_END_OF_FILE;
     387
    357388    /* Format the checksum */
    358     RTStrPrintf(pRecord->h.chksum, sizeof(pRecord->h.chksum), "%0.7o", uChkSum);
     389    RTStrPrintf(pRecord->h.chksum, sizeof(pRecord->h.chksum), "%0.7o", iUnsignedChksum);
    359390
    360391    return VINF_SUCCESS;
注意: 瀏覽 TracChangeset 來幫助您使用更動檢視器

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette