From 6fd3371e94fa529e39a9c047f2eef81f3b4ec43c Mon Sep 17 00:00:00 2001 From: eta Date: Thu, 2 Jul 2020 22:32:25 +0100 Subject: feat(tvldb): prohibit infinite recursion Change-Id: I63b54e937f4c4fdb823f2e2e91a5a5d8af071a42 Reviewed-on: https://cl.tvl.fyi/c/depot/+/855 Tested-by: BuildkiteCI Reviewed-by: eta Reviewed-by: isomer Reviewed-by: BuildkiteCI --- fun/tvldb/src/keyword.rs | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/fun/tvldb/src/keyword.rs b/fun/tvldb/src/keyword.rs index fe296f03df..9c5ea47ea5 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, @@ -162,10 +165,11 @@ impl KeywordDetails { Ok(entries) } - pub fn get<'a, T: Into>>( + fn get_inner<'a, T: Into>>( word: T, c: &str, dbc: &PgConnection, + recursion_count: usize, ) -> Result, Error> { let word = word.into(); let keyword: Option = { @@ -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>>( + word: T, + c: &str, + dbc: &PgConnection, + ) -> Result, Error> { + Self::get_inner(word, c, dbc, 0) + } } -- cgit 1.4.1