diff options
author | Kamil Musin <kamilm@google.com> | 2023-12-05 16:22:08 +0100 |
---|---|---|
committer | Ivan Frade <ifrade@google.com> | 2023-12-05 16:00:41 -0800 |
commit | ab132937fbd5aadfae5fc271b680a2f7a8e7f3a2 (patch) | |
tree | e02f36c68e1f4501012b9d50e8a6fd3752267875 | |
parent | f75e8fb4253fc15c7364853b1e88a960a51b2ce1 (diff) | |
download | jgit-ab132937fbd5aadfae5fc271b680a2f7a8e7f3a2.tar.gz jgit-ab132937fbd5aadfae5fc271b680a2f7a8e7f3a2.zip |
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
-rw-r--r-- | org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/FooterLineTest.java | 18 | ||||
-rw-r--r-- | org.eclipse.jgit/src/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 @@ -80,6 +80,24 @@ public class FooterLineTest extends RepositoryTestCase { } @Test + public void testNoFooters_noRawMsg_SingleLineNoHeaders() { + String noRawMsg = "commit message with no header lines\n"; + List<FooterLine> 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<FooterLine> 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" + "Signed-off-by: A. U. Thor <a@example.com>"); 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 |