From f029530671255f5e1ed367125b380687ee014583 Mon Sep 17 00:00:00 2001 From: deathaxe Date: Sat, 6 Jan 2024 17:55:30 +0100 Subject: [PATCH] Fix IndexError caused by invalid tags (#348) `TagFile` class' __getitem__() method returns `Tag` objects for invalid tags with only one column or even for empty lines. This causes index errors, when trying to access non-existing columns (not enough \t present in a line). --- ctags.py | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/ctags.py b/ctags.py index fdff8b2..e506bf5 100644 --- a/ctags.py +++ b/ctags.py @@ -393,16 +393,26 @@ def __init__(self, line, column=0): self.column = column def __lt__(self, other): - return self.line.split('\t')[self.column] < other + try: + return self.key < other + except IndexError: + return False def __gt__(self, other): - return self.line.split('\t')[self.column] > other + try: + return self.key > other + except IndexError: + return False def __getitem__(self, index): - return self.line.split('\t')[index] + return self.line.split('\t', self.column + 1)[index] def __len__(self): - return len(self.line.split('\t')) + return self.line.count('\t') + 1 + + @property + def key(self): + return self[self.column] class TagFile(object): """ @@ -443,6 +453,8 @@ def __getitem__(self, index): result = self.mapped.readline() # get a complete line result = result.strip() + if not result: + raise IndexError("Invalid tag at index %d." % index) return Tag(result, self.column) @@ -500,7 +512,8 @@ def search(self, exact_match=True, *tags): if not tags: while self.mapped.tell() < self.mapped.size(): result = Tag(self.mapped.readline().strip(), self.column) - yield(result) + if result.line: + yield result return for key in tags: @@ -508,12 +521,12 @@ def search(self, exact_match=True, *tags): if exact_match: result = self[left_index] while result.line and result[result.column] == key: - yield(result) + yield result result = Tag(self.mapped.readline().strip(), self.column) else: result = self[left_index] while result.line and result[result.column].startswith(key): - yield(result) + yield result result = Tag(self.mapped.readline().strip(), self.column) def search_by_suffix(self, suffix): @@ -529,10 +542,9 @@ def search_by_suffix(self, suffix): :returns: matching tags """ for line in self.file_o: - if line.split('\t')[self.column].endswith(suffix): - yield Tag(line) - else: - continue + tag = Tag(line, self.column) + if tag.key.endswith(suffix): + yield tag def tag_class(self): """