Fix handling of Tar PaxHeaders

- relax PaxHeader name check and add mtime pax property parsing
- patch submitted by Vladimir Surguchev
This commit is contained in:
Tino Reichardt
2021-05-17 22:46:22 +02:00
parent 3c1c9c5346
commit c894c2f88b

View File

@@ -368,13 +368,13 @@ static HRESULT ReadDataToString(ISequentialInStream *stream, CItemEx &item, AStr
return S_OK; return S_OK;
} }
static bool ParsePaxLongName(const AString &src, AString &dest) static bool ParsePaxParams(const AString& src, AString& pax_path, Int64& pax_mtime)
{ {
dest.Empty(); pax_path.Empty();
for (unsigned pos = 0;;) for (unsigned pos = 0;;)
{ {
if (pos >= src.Len()) if (pos >= src.Len())
return false; return true; // false;
const char *start = src.Ptr(pos); const char *start = src.Ptr(pos);
const char *end; const char *end;
const UInt32 lineLen = ConvertStringToUInt32(start, &end); const UInt32 lineLen = ConvertStringToUInt32(start, &end);
@@ -382,7 +382,9 @@ static bool ParsePaxLongName(const AString &src, AString &dest)
return false; return false;
if (*end != ' ') if (*end != ' ')
return false; return false;
if (lineLen > src.Len() - pos) if (lineLen <= 0 || lineLen > src.Len() - pos)
return false;
if (start[lineLen - 1] != '\n')
return false; return false;
unsigned offset = (unsigned)(end - start) + 1; unsigned offset = (unsigned)(end - start) + 1;
if (lineLen < offset) if (lineLen < offset)
@@ -390,13 +392,32 @@ static bool ParsePaxLongName(const AString &src, AString &dest)
if (IsString1PrefixedByString2(src.Ptr(pos + offset), "path=")) if (IsString1PrefixedByString2(src.Ptr(pos + offset), "path="))
{ {
offset += 5; // "path=" offset += 5; // "path="
dest = src.Mid(pos + offset, lineLen - offset); pax_path = src.Mid(pos + offset, lineLen - offset - 1);
if (dest.IsEmpty()) }
return false; else if (IsString1PrefixedByString2(src.Ptr(pos + offset), "mtime="))
if (dest.Back() != '\n') {
return false; Int64 v = 0; int mult = 10 * 1000 * 1000;
dest.DeleteBack(); offset += 6; // "mtime=ssssssssss.ccccccc"
return true; bool after_dot = false;
for (;;) {
const char c = start[offset++];
if (c >= '0' && c <= '9') {
v = 10 * v + (c - '0');
if (after_dot) {
mult /= 10;
if (mult == 1)
break;
}
}
else {
if (c == '.')
after_dot = true;
else
break;
}
}
if (v > 0)
pax_mtime = v * mult;
} }
pos += lineLen; pos += lineLen;
} }
@@ -459,6 +480,9 @@ HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &item, EErro
if (IsString1PrefixedByString2(s, "./")) if (IsString1PrefixedByString2(s, "./"))
s += 2; s += 2;
if ( IsString1PrefixedByString2(s, "PaxHeader/") if ( IsString1PrefixedByString2(s, "PaxHeader/")
|| item.Name.Find("/PaxHeader/") >= 0
|| IsString1PrefixedByString2(s, "PaxHeaders/")
|| item.Name.Find("/PaxHeaders/") >= 0
|| IsString1PrefixedByString2(s, "PaxHeaders.X/") || IsString1PrefixedByString2(s, "PaxHeaders.X/")
|| IsString1PrefixedByString2(s, "PaxHeaders.4467/") || IsString1PrefixedByString2(s, "PaxHeaders.4467/")
|| StringsAreEqual_Ascii(s, "@PaxHeader") || StringsAreEqual_Ascii(s, "@PaxHeader")
@@ -503,8 +527,14 @@ HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &item, EErro
if (!pax.IsEmpty()) if (!pax.IsEmpty())
{ {
AString name; AString name;
if (ParsePaxLongName(pax, name)) Int64 mtime = 0;
item.Name = name; if (ParsePaxParams(pax, name, mtime))
{
if (!name.IsEmpty())
item.Name = name;
if (mtime > 0)
item.MTime = mtime;
}
else else
{ {
// no "path" property is allowed in pax4467 // no "path" property is allowed in pax4467