Skip to content

Commit a9eb5f0

Browse files
authored
Rollup merge of #94260 - GuillaumeGomez:infinite-redirection, r=notriddle
Fix rustdoc infinite redirection generation Someone came to me about a funny bug they had when clicking on any link on [this page](https://world.pages.gitlab.gnome.org/Rust/libadwaita-rs/stable/latest/docs/libadwaita/builders/index.html): it ended one page redirecting to itself indefinitely. I was able to make a minimum reproducible case to trigger this bug which I now use as a test. r? ``@notriddle``
2 parents 09e4f34 + 1d95acb commit a9eb5f0

File tree

2 files changed

+63
-26
lines changed

2 files changed

+63
-26
lines changed

src/librustdoc/html/render/context.rs

+34-26
Original file line numberDiff line numberDiff line change
@@ -201,19 +201,19 @@ impl<'tcx> Context<'tcx> {
201201
} else {
202202
tyname.as_str()
203203
};
204-
let page = layout::Page {
205-
css_class: tyname_s,
206-
root_path: &self.root_path(),
207-
static_root_path: self.shared.static_root_path.as_deref(),
208-
title: &title,
209-
description: &desc,
210-
keywords: &keywords,
211-
resource_suffix: &self.shared.resource_suffix,
212-
extra_scripts: &[],
213-
static_extra_scripts: &[],
214-
};
215204

216205
if !self.render_redirect_pages {
206+
let page = layout::Page {
207+
css_class: tyname_s,
208+
root_path: &self.root_path(),
209+
static_root_path: self.shared.static_root_path.as_deref(),
210+
title: &title,
211+
description: &desc,
212+
keywords: &keywords,
213+
resource_suffix: &self.shared.resource_suffix,
214+
extra_scripts: &[],
215+
static_extra_scripts: &[],
216+
};
217217
layout::render(
218218
&self.shared.layout,
219219
&page,
@@ -223,23 +223,31 @@ impl<'tcx> Context<'tcx> {
223223
)
224224
} else {
225225
if let Some(&(ref names, ty)) = self.cache().paths.get(&it.def_id.expect_def_id()) {
226-
let mut path = String::new();
227-
for name in &names[..names.len() - 1] {
228-
path.push_str(&name.as_str());
229-
path.push('/');
230-
}
231-
path.push_str(&item_path(ty, &names.last().unwrap().as_str()));
232-
match self.shared.redirections {
233-
Some(ref redirections) => {
234-
let mut current_path = String::new();
235-
for name in &self.current {
236-
current_path.push_str(&name.as_str());
237-
current_path.push('/');
226+
if self.current.len() + 1 != names.len()
227+
|| self.current.iter().zip(names.iter()).any(|(a, b)| a != b)
228+
{
229+
// We checked that the redirection isn't pointing to the current file,
230+
// preventing an infinite redirection loop in the generated
231+
// documentation.
232+
233+
let mut path = String::new();
234+
for name in &names[..names.len() - 1] {
235+
path.push_str(&name.as_str());
236+
path.push('/');
237+
}
238+
path.push_str(&item_path(ty, &names.last().unwrap().as_str()));
239+
match self.shared.redirections {
240+
Some(ref redirections) => {
241+
let mut current_path = String::new();
242+
for name in &self.current {
243+
current_path.push_str(&name.as_str());
244+
current_path.push('/');
245+
}
246+
current_path.push_str(&item_path(ty, &names.last().unwrap().as_str()));
247+
redirections.borrow_mut().insert(current_path, path);
238248
}
239-
current_path.push_str(&item_path(ty, &names.last().unwrap().as_str()));
240-
redirections.borrow_mut().insert(current_path, path);
249+
None => return layout::redirect(&format!("{}{}", self.root_path(), path)),
241250
}
242-
None => return layout::redirect(&format!("{}{}", self.root_path(), path)),
243251
}
244252
}
245253
String::new()
+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#![crate_name = "foo"]
2+
3+
// This test ensures that there is no "infinite redirection" file generated (a
4+
// file which redirects to itself).
5+
6+
// We check it's not a redirection file.
7+
// @has 'foo/builders/struct.ActionRowBuilder.html'
8+
// @has - '//*[@id="synthetic-implementations"]' 'Auto Trait Implementations'
9+
10+
// And that the link in the module is targetting it.
11+
// @has 'foo/builders/index.html'
12+
// @has - '//a[@href="struct.ActionRowBuilder.html"]' 'ActionRowBuilder'
13+
14+
mod auto {
15+
mod action_row {
16+
pub struct ActionRowBuilder;
17+
}
18+
19+
#[doc(hidden)]
20+
pub mod builders {
21+
pub use super::action_row::ActionRowBuilder;
22+
}
23+
}
24+
25+
pub use auto::*;
26+
27+
pub mod builders {
28+
pub use crate::auto::builders::*;
29+
}

0 commit comments

Comments
 (0)