From ab132937fbd5aadfae5fc271b680a2f7a8e7f3a2 Mon Sep 17 00:00:00 2001 From: Kamil Musin Date: Tue, 5 Dec 2023 16:22:08 +0100 Subject: [PATCH] FooterLine: Protect from ill-formed message A raw commit message has some headers and then the actual message. RawParseUtils.commitMessage returns the start position of the actual message, or -1 when the message is not raw. FooterLine is not handling this -1 and throws an IndexOutOfBounds exception. Consider than msgB can be -1 when looking for the beginning of the last paragraph. FooterLine javadoc and parameter talk only about "raw" but previous code accepted non-raw messages (used mostly in unit tests) so we need to keep this behavior. Change-Id: I4b88c507e210fdd200a85b01665c8524ab393b00 --- .../eclipse/jgit/revwalk/FooterLineTest.java | 18 ++++++++++++++++++ .../org/eclipse/jgit/revwalk/FooterLine.java | 14 +++++++++++--- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/FooterLineTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/FooterLineTest.java index ca6fd4644e..a6808f6351 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/FooterLineTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/FooterLineTest.java @@ -79,6 +79,24 @@ public class FooterLineTest extends RepositoryTestCase { assertEquals(0, footers.size()); } + @Test + public void testNoFooters_noRawMsg_SingleLineNoHeaders() { + String noRawMsg = "commit message with no header lines\n"; + List footers = FooterLine.fromMessage(noRawMsg); + assertNotNull(footers); + assertEquals(0, footers.size()); + } + + @Test + public void testOneFooter_noRawMsg_MultiParagraphNoHeaders() { + String noRawMsg = "subject\n\n" + + "Not: footer\n\n" + + "Footer: value\n"; + List footers = FooterLine.fromMessage(noRawMsg); + assertNotNull(footers); + assertEquals(1, footers.size()); + } + @Test public void testSignedOffBy_OneUserNoLF() { String msg = buildMessage("subject\n\nbody of commit\n" + "\n" diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/FooterLine.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/FooterLine.java index 3968617f8f..d651b63afb 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/FooterLine.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/FooterLine.java @@ -87,8 +87,15 @@ public final class FooterLine { // Search for the beginning of last paragraph int parStart = parEnd; - for (; parStart > msgB && (raw[parStart - 1] != '\n' || raw[parStart - 2] != '\n'); --parStart) { - // empty + for (; parStart > msgB; --parStart) { + if (parStart < 2) { + // Too close to beginning: this is not a raw message + parStart = 0; + break; + } + if (raw[parStart - 1] == '\n' && raw[parStart - 2] == '\n') { + break; + } } for (int ptr = parStart; ptr < parEnd;) { @@ -101,7 +108,8 @@ public final class FooterLine { } // Skip over the ': *' at the end of the key before the value. - int valStart, valEnd; + int valStart; + int valEnd; for (valStart = keyEnd + 1; valStart < raw.length && raw[valStart] == ' '; ++valStart) { // empty -- 2.39.5