Skip to content

Commit 5d6bea7

Browse files
committed
introspection: fail on not supported introspection symbol version
Allows a clean error if a too old pyo3-introspection version is used
1 parent 92bbf01 commit 5d6bea7

1 file changed

Lines changed: 18 additions & 3 deletions

File tree

pyo3-introspection/src/introspection.rs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -564,11 +564,13 @@ fn find_introspection_chunks_in_binary_object(path: &Path) -> Result<Vec<Chunk>>
564564
fn find_introspection_chunks_in_elf(elf: &Elf<'_>, library_content: &[u8]) -> Result<Vec<Chunk>> {
565565
let mut chunks = Vec::new();
566566
for sym in &elf.syms {
567-
if is_introspection_symbol(elf.strtab.get_at(sym.st_name).unwrap_or_default()) {
567+
let sym_name = elf.strtab.get_at(sym.st_name).unwrap_or_default();
568+
if is_introspection_symbol(sym_name) {
568569
ensure!(u32::try_from(sym.st_shndx)? != SHN_XINDEX, "Section names length is greater than SHN_LORESERVE in ELF, this is not supported by PyO3 yet");
569570
let section_header = &elf.section_headers[sym.st_shndx];
570571
let data_offset = sym.st_value + section_header.sh_offset - section_header.sh_addr;
571572
chunks.push(deserialize_chunk(
573+
sym_name,
572574
&library_content[usize::try_from(data_offset).context("File offset overflow")?..],
573575
elf.little_endian,
574576
)?);
@@ -608,6 +610,7 @@ fn find_introspection_chunks_in_macho(
608610
let section = &sections[nlist.n_sect - 1]; // Sections are counted from 1
609611
let data_offset = nlist.n_value + u64::from(section.offset) - section.addr;
610612
chunks.push(deserialize_chunk(
613+
name,
611614
&library_content[usize::try_from(data_offset).context("File offset overflow")?..],
612615
macho.little_endian,
613616
)?);
@@ -621,6 +624,7 @@ fn find_introspection_chunks_in_pe(pe: &PE<'_>, library_content: &[u8]) -> Resul
621624
for export in &pe.exports {
622625
if is_introspection_symbol(export.name.unwrap_or_default()) {
623626
chunks.push(deserialize_chunk(
627+
export.name.unwrap_or_default(),
624628
&library_content[export.offset.context("No symbol offset")?..],
625629
true,
626630
)?);
@@ -630,9 +634,14 @@ fn find_introspection_chunks_in_pe(pe: &PE<'_>, library_content: &[u8]) -> Resul
630634
}
631635

632636
fn deserialize_chunk(
637+
symbol_name: &str,
633638
content_with_chunk_at_the_beginning: &[u8],
634639
is_little_endian: bool,
635640
) -> Result<Chunk> {
641+
let symbol_version = introspection_symbol_version(symbol_name).unwrap_or_default();
642+
if symbol_version != "1" {
643+
bail!("The introspection format version '{symbol_version}' is not supported by this version of pyo3-introspection. Please upgrade your build tool like maturin or downgrade pyo3");
644+
}
636645
let length = content_with_chunk_at_the_beginning
637646
.split_at(4)
638647
.0
@@ -657,9 +666,15 @@ fn deserialize_chunk(
657666
}
658667

659668
fn is_introspection_symbol(name: &str) -> bool {
660-
name.strip_prefix('_')
669+
introspection_symbol_version(name).is_some()
670+
}
671+
672+
fn introspection_symbol_version(name: &str) -> Option<&str> {
673+
let name = name
674+
.strip_prefix('_')
661675
.unwrap_or(name)
662-
.starts_with("PYO3_INTROSPECTION_1_")
676+
.strip_prefix("PYO3_INTROSPECTION_")?;
677+
Some(name.split_once('_').unwrap_or((name, "")).0)
663678
}
664679

665680
#[derive(Deserialize)]

0 commit comments

Comments
 (0)