public Model(Stream stream, byte[] hdr, string path) { base._data = Data = new FlvFormat(this, stream, path); var bb = new byte[15]; Data.flags = hdr[4]; if ((Data.flags & 0xA) != 0) { IssueModel.Add("Unexpected flags."); } if ((Data.flags & 5) == 0) { IssueModel.Add("Missing audio and video."); } UInt32 hdrSize = ConvertTo.FromBig32ToUInt32(hdr, 5); if (hdrSize != 9) { IssueModel.Add("Wrong header size."); } Data.mediaPosition = 9; UInt32 actualPrevSize = 0; while (Data.mediaPosition < Data.FileSize) { if (Data.mediaPosition + 15 > Data.FileSize) { IssueModel.Add("File truncated near packet header.", Severity.Fatal); return; } Data.fbs.Position = Data.mediaPosition; var got = Data.fbs.Read(bb, 0, bb.Length); if (got < bb.Length) { IssueModel.Add("Read error", Severity.Fatal); return; } Data.mediaPosition += 15; UInt32 storedPrevSize = ConvertTo.FromBig32ToUInt32(bb, 0); if (storedPrevSize != actualPrevSize) { IssueModel.Add("Bad previous packet size."); } byte packetType = bb[4]; UInt32 packetSize = ConvertTo.FromBig24ToUInt32(bb, 5); actualPrevSize = packetSize + 11; ++Data.PacketCount; Data.mediaPosition += packetSize; } if (Data.mediaPosition > Data.FileSize) { IssueModel.Add("File truncated.", Severity.Fatal); } }
private void ParseAif(Stream stream, byte[] hdr) { Data.GroupId = ConvertTo.FromAsciiToString(hdr, 0, 4); Data.FormType = ConvertTo.FromAsciiToString(hdr, 8, 4); UInt32 gSize = ConvertTo.FromBig32ToUInt32(hdr, 4); if (gSize < 12 || gSize > stream.Length - 8) { IssueModel.Add("File truncated or corrupt.", Severity.Fatal); return; } int hPos = 12; string id0 = ConvertTo.FromAsciiToString(hdr, 12, 4); if (Data.IsCompressed) { if (id0 != "FVER") { IssueModel.Add("Missing 'FVER' chunk."); return; } UInt32 vSize = ConvertTo.FromBig32ToUInt32(hdr, 16); if (vSize != 4) { IssueModel.Add("Bad 'FVER' chunk."); return; } hPos = 24; id0 = ConvertTo.FromAsciiToString(hdr, 24, 4); } if (id0 != "COMM") { IssueModel.Add("Missing 'COMM' chunk."); return; } UInt32 cSize = ConvertTo.FromBig32ToUInt32(hdr, hPos + 4); if (cSize < 18 || cSize > stream.Length - 8) { IssueModel.Add("Bad 'COMM' chunk."); return; } Data.ChannelCount = ConvertTo.FromBig16ToInt32(hdr, hPos + 8); Data.SampleSize = ConvertTo.FromBig16ToInt32(hdr, hPos + 14); ++Data.IffChunkCount; Data.IffSize = gSize; Data.mediaPosition = 0; Data.MediaCount = gSize + 8; Data.ValidSize = hPos + cSize + 8; var hasSSND = false; var buf = new byte[8]; while (Data.ValidSize < Data.MediaCount) { stream.Position = Data.ValidSize; int got = stream.Read(buf, 0, 8); if (got != 8) { IssueModel.Add("Read failed."); return; } cSize = ConvertTo.FromBig32ToUInt32(buf, 4); if (cSize < 8 || Data.ValidSize + cSize > Data.MediaCount - 8) { IssueModel.Add("Bad chunk size or truncated file."); return; } string id = ConvertTo.FromAsciiToString(buf, 0, 4); if (id == "SSND") { if (hasSSND) { IssueModel.Add("Many 'SSND' chunks."); return; } hasSSND = true; } else if (id != "(c) " && id != "ANNO" && id != "AUTH" && id != "NAME") { IssueModel.Add($"Unexpected '{id}' chunk.", Severity.Trivia, IssueTags.StrictWarn); return; } Data.ValidSize += cSize + 8; if ((cSize & 1) != 0) { ++Data.ValidSize; } } if (!hasSSND) { IssueModel.Add("Missing 'SSND' chunk.", Severity.Warning); } }
public Model(Stream stream, string path) { ChunksModel = new PngChunk.Vector.Model(); base._data = Data = new PngFormat(this, stream, path); // Arbitrary sanity limit. if (Data.FileSize > 100000000) { IssueModel.Add("File size insanely huge.", Severity.Fatal); return; } Data.fBuf = new byte[(int)Data.FileSize]; var fBuf = Data.fBuf; stream.Position = 0; int got = stream.Read(fBuf, 0, (int)Data.FileSize); if (got < Data.FileSize) { IssueModel.Add("Read failed.", Severity.Fatal); return; } Data.ValidSize = 8; do { UInt32 chunkSize = ConvertTo.FromBig32ToUInt32(fBuf, (int)Data.ValidSize); if (Data.ValidSize + chunkSize + 12 > Data.FileSize) { IssueModel.Add("File is corrupt or truncated.", Severity.Fatal); return; } string type = Encoding.ASCII.GetString(fBuf, (int)Data.ValidSize + 4, 4); UInt32 storedCRC = ConvertTo.FromBig32ToUInt32(fBuf, (int)(Data.ValidSize + chunkSize + 8)); ChunksModel.Add(type, chunkSize, storedCRC); var typeLow = type.ToLower(); switch (typeLow) { case "idat": if (Data.mediaPosition <= 0) { Data.mediaPosition = Data.ValidSize; } break; case "iend": if (Data.MediaCount > 0) { IssueModel.Add("Multiple IEND chunks."); } else { Data.MediaCount = Data.ValidSize - Data.mediaPosition + chunkSize + 0xC; } break; case "ihdr": if (chunkSize < 13) { IssueModel.Add("IHDR chunk is short."); } else if (Data.Width != null) { IssueModel.Add("Multiple IHDR chunks."); } else { Data.Width = ConvertTo.FromBig32ToInt32(fBuf, (int)Data.ValidSize + 8); Data.Height = ConvertTo.FromBig32ToInt32(fBuf, (int)Data.ValidSize + 12); Data.BitDepth = fBuf[(int)Data.ValidSize + 16]; Data.ColorType = fBuf[(int)Data.ValidSize + 17]; Data.CompressionMethod = fBuf[(int)Data.ValidSize + 18]; Data.FilterMethod = fBuf[(int)Data.ValidSize + 19]; Data.InterlaceMethod = fBuf[(int)Data.ValidSize + 20]; } break; case "phys": if (chunkSize < 9) { IssueModel.Add("PHYS chunk is short."); } else if (Data.DotsPerMeter1 != null) { IssueModel.Add("Multiple PHYS chunks."); } else { Data.DotsPerMeter1 = ConvertTo.FromBig32ToInt32(fBuf, (int)Data.ValidSize + 8); Data.DotsPerMeter2 = ConvertTo.FromBig32ToInt32(fBuf, (int)Data.ValidSize + 12); Data.Units = fBuf[(int)Data.ValidSize + 9]; } break; case "text": if (chunkSize > 0x7FFF) { IssueModel.Add("String size too large."); } else { var escaped = new StringBuilder(); for (int ix = (int)Data.ValidSize + 8; ix < (int)Data.ValidSize + 8 + chunkSize; ++ix) { if (fBuf[ix] < ' ' || fBuf[ix] > 0x7F) { escaped.Append($"\\{fBuf[ix]:x2}"); } else { escaped.Append((char)fBuf[ix]); } } Data.texts.Add(escaped.ToString()); } break; case "gama": if (chunkSize < 4) { IssueModel.Add("GAMA chunk is short."); } else if (Data.Gamma != null) { IssueModel.Add("Multiple GAMA chunks."); } else { Data.Gamma = ConvertTo.FromBig32ToUInt32(fBuf, (int)Data.ValidSize + 8) / 100000f; } break; } Data.ValidSize += chunkSize + 0xC; }while (Data.ValidSize < Data.FileSize); if (Data.Width == null) { IssueModel.Add("Missing IHDR chunk."); } if (Data.Chunks.Items[Data.Chunks.Items.Count - 1].Type != "IEND") { IssueModel.Add("Missing IEND chunk."); } if (Data.Width <= 0 || Data.Height <= 0) { IssueModel.Add("Invalid dimensions."); } if (Data.DotsPerMeter1 != Data.DotsPerMeter2) { IssueModel.Add("Density aspect not 1.", Severity.Warning); } if (Data.BitDepth != 1 && Data.BitDepth != 2 && Data.BitDepth != 4 && Data.BitDepth != 8 && Data.BitDepth != 16) { IssueModel.Add($"Invalid bit depth '{Data.BitDepth}'."); } if (Data.CompressionMethod != 0) { IssueModel.Add($"Invalid compression '{Data.CompressionMethod}'."); } if (Data.FilterMethod != 0) { IssueModel.Add($"Invalid filter '{Data.FilterMethod}'."); } if (Data.InterlaceMethod != 0 && Data.InterlaceMethod != 1) { IssueModel.Add($"Invalid interlace '{Data.InterlaceMethod}'."); } }