Add comprehensive tests for Go and Python version conflict detection and licensing normalization
- Implemented GoVersionConflictDetectorTests to validate pseudo-version detection, conflict analysis, and conflict retrieval for Go modules. - Created VersionConflictDetectorTests for Python to assess conflict detection across various version scenarios, including major, minor, and patch differences. - Added SpdxLicenseNormalizerTests to ensure accurate normalization of SPDX license strings and classifiers. - Developed VendoredPackageDetectorTests to identify vendored packages and extract embedded packages from Python packages, including handling of vendor directories and known vendored packages.
This commit is contained in:
@@ -321,4 +321,106 @@ public class ElfDynamicSectionParserTests
|
||||
buffer[offset + bytes.Length] = 0; // null terminator
|
||||
return bytes.Length;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParsesElfWithVersionNeeds()
|
||||
{
|
||||
// Test that version needs (GLIBC_2.17, etc.) are properly extracted
|
||||
var buffer = new byte[4096];
|
||||
SetupElf64Header(buffer, littleEndian: true);
|
||||
|
||||
// String table at offset 0x400
|
||||
var strtab = 0x400;
|
||||
var libcOffset = 1; // "libc.so.6"
|
||||
var glibc217Offset = libcOffset + WriteString(buffer, strtab + libcOffset, "libc.so.6") + 1;
|
||||
var glibc228Offset = glibc217Offset + WriteString(buffer, strtab + glibc217Offset, "GLIBC_2.17") + 1;
|
||||
var strtabSize = glibc228Offset + WriteString(buffer, strtab + glibc228Offset, "GLIBC_2.28") + 1;
|
||||
|
||||
// Section headers at offset 0x800
|
||||
var shoff = 0x800;
|
||||
var shentsize = 64;
|
||||
var shnum = 3; // null + .dynstr + .gnu.version_r
|
||||
|
||||
BitConverter.GetBytes((ulong)shoff).CopyTo(buffer, 40);
|
||||
BitConverter.GetBytes((ushort)shentsize).CopyTo(buffer, 58);
|
||||
BitConverter.GetBytes((ushort)shnum).CopyTo(buffer, 60);
|
||||
|
||||
// Section header 0: null
|
||||
// Section header 1: .dynstr
|
||||
var sh1 = shoff + shentsize;
|
||||
BitConverter.GetBytes((uint)3).CopyTo(buffer, sh1 + 4); // sh_type = SHT_STRTAB
|
||||
BitConverter.GetBytes((ulong)0x400).CopyTo(buffer, sh1 + 16); // sh_addr
|
||||
BitConverter.GetBytes((ulong)strtab).CopyTo(buffer, sh1 + 24); // sh_offset
|
||||
BitConverter.GetBytes((ulong)strtabSize).CopyTo(buffer, sh1 + 32); // sh_size
|
||||
|
||||
// Section header 2: .gnu.version_r (SHT_GNU_verneed = 0x6ffffffe)
|
||||
var verneedFileOffset = 0x600;
|
||||
var sh2 = shoff + shentsize * 2;
|
||||
BitConverter.GetBytes((uint)0x6ffffffe).CopyTo(buffer, sh2 + 4); // sh_type = SHT_GNU_verneed
|
||||
BitConverter.GetBytes((ulong)0x600).CopyTo(buffer, sh2 + 16); // sh_addr (vaddr)
|
||||
BitConverter.GetBytes((ulong)verneedFileOffset).CopyTo(buffer, sh2 + 24); // sh_offset
|
||||
|
||||
// Version needs section at offset 0x600
|
||||
// Verneed entry for libc.so.6 with two version requirements
|
||||
// Elf64_Verneed: vn_version(2), vn_cnt(2), vn_file(4), vn_aux(4), vn_next(4)
|
||||
var verneedOffset = verneedFileOffset;
|
||||
BitConverter.GetBytes((ushort)1).CopyTo(buffer, verneedOffset); // vn_version = 1
|
||||
BitConverter.GetBytes((ushort)2).CopyTo(buffer, verneedOffset + 2); // vn_cnt = 2 aux entries
|
||||
BitConverter.GetBytes((uint)libcOffset).CopyTo(buffer, verneedOffset + 4); // vn_file -> "libc.so.6"
|
||||
BitConverter.GetBytes((uint)16).CopyTo(buffer, verneedOffset + 8); // vn_aux = 16 (offset to first aux)
|
||||
BitConverter.GetBytes((uint)0).CopyTo(buffer, verneedOffset + 12); // vn_next = 0 (last entry)
|
||||
|
||||
// Vernaux entries
|
||||
// Elf64_Vernaux: vna_hash(4), vna_flags(2), vna_other(2), vna_name(4), vna_next(4)
|
||||
var aux1Offset = verneedOffset + 16;
|
||||
BitConverter.GetBytes((uint)0x0d696910).CopyTo(buffer, aux1Offset); // vna_hash for GLIBC_2.17
|
||||
BitConverter.GetBytes((ushort)0).CopyTo(buffer, aux1Offset + 4); // vna_flags
|
||||
BitConverter.GetBytes((ushort)2).CopyTo(buffer, aux1Offset + 6); // vna_other
|
||||
BitConverter.GetBytes((uint)glibc217Offset).CopyTo(buffer, aux1Offset + 8); // vna_name -> "GLIBC_2.17"
|
||||
BitConverter.GetBytes((uint)16).CopyTo(buffer, aux1Offset + 12); // vna_next = 16 (offset to next aux)
|
||||
|
||||
var aux2Offset = aux1Offset + 16;
|
||||
BitConverter.GetBytes((uint)0x09691974).CopyTo(buffer, aux2Offset); // vna_hash for GLIBC_2.28
|
||||
BitConverter.GetBytes((ushort)0).CopyTo(buffer, aux2Offset + 4);
|
||||
BitConverter.GetBytes((ushort)3).CopyTo(buffer, aux2Offset + 6);
|
||||
BitConverter.GetBytes((uint)glibc228Offset).CopyTo(buffer, aux2Offset + 8); // vna_name -> "GLIBC_2.28"
|
||||
BitConverter.GetBytes((uint)0).CopyTo(buffer, aux2Offset + 12); // vna_next = 0 (last aux)
|
||||
|
||||
// Dynamic section at offset 0x200
|
||||
var dynOffset = 0x200;
|
||||
var dynEntrySize = 16;
|
||||
var dynIndex = 0;
|
||||
|
||||
WriteDynEntry64(buffer, dynOffset + dynEntrySize * dynIndex++, 5, 0x400); // DT_STRTAB
|
||||
WriteDynEntry64(buffer, dynOffset + dynEntrySize * dynIndex++, 10, (ulong)strtabSize); // DT_STRSZ
|
||||
WriteDynEntry64(buffer, dynOffset + dynEntrySize * dynIndex++, 1, (ulong)libcOffset); // DT_NEEDED -> libc.so.6
|
||||
WriteDynEntry64(buffer, dynOffset + dynEntrySize * dynIndex++, 0x6ffffffe, 0x600); // DT_VERNEED (vaddr)
|
||||
WriteDynEntry64(buffer, dynOffset + dynEntrySize * dynIndex++, 0x6fffffff, 1); // DT_VERNEEDNUM = 1
|
||||
WriteDynEntry64(buffer, dynOffset + dynEntrySize * dynIndex, 0, 0); // DT_NULL
|
||||
|
||||
var dynSize = dynEntrySize * (dynIndex + 1);
|
||||
|
||||
// Program header
|
||||
var phoff = 0x40;
|
||||
var phentsize = 56;
|
||||
var phnum = 1;
|
||||
|
||||
BitConverter.GetBytes((ulong)phoff).CopyTo(buffer, 32);
|
||||
BitConverter.GetBytes((ushort)phentsize).CopyTo(buffer, 54);
|
||||
BitConverter.GetBytes((ushort)phnum).CopyTo(buffer, 56);
|
||||
|
||||
BitConverter.GetBytes((uint)2).CopyTo(buffer, phoff); // PT_DYNAMIC
|
||||
BitConverter.GetBytes((ulong)dynOffset).CopyTo(buffer, phoff + 8);
|
||||
BitConverter.GetBytes((ulong)dynSize).CopyTo(buffer, phoff + 32);
|
||||
|
||||
using var stream = new MemoryStream(buffer);
|
||||
var result = ElfDynamicSectionParser.TryParse(stream, out var info);
|
||||
|
||||
result.Should().BeTrue();
|
||||
info.Dependencies.Should().HaveCount(1);
|
||||
info.Dependencies[0].Soname.Should().Be("libc.so.6");
|
||||
info.Dependencies[0].VersionNeeds.Should().HaveCount(2);
|
||||
info.Dependencies[0].VersionNeeds.Should().Contain(v => v.Version == "GLIBC_2.17");
|
||||
info.Dependencies[0].VersionNeeds.Should().Contain(v => v.Version == "GLIBC_2.28");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user