diff options
author | eta <eta@theta.eu.org> | 2020-07-02T21·32+0100 |
---|---|---|
committer | eta <eta@theta.eu.org> | 2020-07-02T21·46+0000 |
commit | 6fd3371e94fa529e39a9c047f2eef81f3b4ec43c (patch) | |
tree | cfddcdf56aff55482ca55fad5603ea00532b5383 /fun/tvldb | |
parent | 1ecae26afa78371dcc77d487a17af4a658d71fd1 (diff) |
feat(tvldb): prohibit infinite recursion r/1173
Change-Id: I63b54e937f4c4fdb823f2e2e91a5a5d8af071a42 Reviewed-on: https://cl.tvl.fyi/c/depot/+/855 Tested-by: BuildkiteCI Reviewed-by: eta <eta@theta.eu.org> Reviewed-by: isomer <isomer@tvl.fyi> Reviewed-by: BuildkiteCI
Diffstat (limited to 'fun/tvldb')
-rw-r--r-- | fun/tvldb/src/keyword.rs | 21 |
1 files changed, 19 insertions, 2 deletions
diff --git a/fun/tvldb/src/keyword.rs b/fun/tvldb/src/keyword.rs index fe296f03df9e..9c5ea47ea523 100644 --- a/fun/tvldb/src/keyword.rs +++ b/fun/tvldb/src/keyword.rs @@ -4,6 +4,9 @@ use diesel::prelude::*; use failure::Error; use std::borrow::Cow; +/// Maximum number of times we'll follow a `see: ` pointer. +const RECURSION_LIMIT: usize = 5; + pub struct KeywordDetails { pub keyword: Keyword, pub entries: Vec<Entry>, @@ -162,10 +165,11 @@ impl KeywordDetails { Ok(entries) } - pub fn get<'a, T: Into<Cow<'a, str>>>( + fn get_inner<'a, T: Into<Cow<'a, str>>>( word: T, c: &str, dbc: &PgConnection, + recursion_count: usize, ) -> Result<Option<Self>, Error> { let word = word.into(); let keyword: Option<Keyword> = { @@ -179,7 +183,12 @@ impl KeywordDetails { let entries = Self::get_entries(k.id, dbc)?; if let Some(e0) = entries.get(0) { if e0.text.starts_with("see: ") { - return Self::get(e0.text.replace("see: ", ""), c, dbc); + if recursion_count > RECURSION_LIMIT { + // Oh dear. + Err(format_err!("Halt. You're having a bit too much fun."))? + } + let new_word = e0.text.replace("see: ", ""); + return Self::get_inner(new_word, c, dbc, recursion_count + 1); } } Ok(Some(KeywordDetails { @@ -190,4 +199,12 @@ impl KeywordDetails { Ok(None) } } + + pub fn get<'a, T: Into<Cow<'a, str>>>( + word: T, + c: &str, + dbc: &PgConnection, + ) -> Result<Option<Self>, Error> { + Self::get_inner(word, c, dbc, 0) + } } |