Skip to content

Commit

Permalink
tests, optional group for diffcmd headers, and release prep
Browse files Browse the repository at this point in the history
bump for release

(hopefully) fix brew install path

export mac test separately

bump pyproject.yaml
  • Loading branch information
cscorley committed Nov 16, 2024
1 parent dadb500 commit 92c1bb6
Show file tree
Hide file tree
Showing 8 changed files with 254 additions and 27 deletions.
9 changes: 8 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]

steps:
- uses: actions/checkout@v4
Expand Down Expand Up @@ -56,6 +56,13 @@ jobs:
- name: Test
run: |
pytest --doctest-modules --doctest-glob='*.rst' --junitxml=junit/test-results-${{ matrix.python-version }}-${{ matrix.os }}.xml
if: ${{ matrix.os != 'macos-latest' }}

- name: Test macos-latest
run: |
export PATH="/opt/homebrew/opt/gpatch/libexec/gnubin:$PATH"
pytest --doctest-modules --doctest-glob='*.rst' --junitxml=junit/test-results-${{ matrix.python-version }}-${{ matrix.os }}.xml
if: ${{ matrix.os == 'macos-latest' }}

- name: Upload pytest test results
uses: actions/upload-artifact@v4
Expand Down
6 changes: 6 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

Nothing yet :)

# 1.0.7

- PR #62 fix: incorrect regular expression matching diffcmd (Thanks, @jingfelix)
- Support up to 3.13
- Drop support up to 3.8

# 1.0.6

- PR #60 Improve huge_patch test (Thanks, @arkamar)
Expand Down
38 changes: 19 additions & 19 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
[project]
name = "whatthepatch"
version = "1.0.6"
version = "1.0.7"
maintainers = [{ name = "Christopher S. Corley", email = "[email protected]" }]
requires-python = ">=3.8"
requires-python = ">=3.9"
readme = "README.rst"
description = "A patch parsing and application library."
keywords = ["patch", "diff", "parser"]
classifiers = [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"Intended Audience :: Science/Research",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: Implementation :: CPython",
"Topic :: Software Development :: Libraries :: Python Modules",
"Topic :: Software Development :: Version Control",
"Topic :: Software Development",
"Topic :: Text Processing",
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"Intended Audience :: Science/Research",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: Implementation :: CPython",
"Topic :: Software Development :: Libraries :: Python Modules",
"Topic :: Software Development :: Version Control",
"Topic :: Software Development",
"Topic :: Text Processing",
]

[project.urls]
Expand Down
4 changes: 2 additions & 2 deletions release.nix
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{ lib, python3Packages, setuptools }:
with python3Packages;
buildPythonPackage rec {
buildPythonPackage {
pname = "whatthepatch";
version = "1.0.6";
version = "1.0.7";
format = "pyproject";
src = ./.;

Expand Down
4 changes: 2 additions & 2 deletions src/whatthepatch/patch.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
# .+? was previously [^:\t\n\r\f\v]+

# general diff regex
diffcmd_header = re.compile("^diff .* (.+) (.+)$")
diffcmd_header = re.compile("^diff(?: .+)? (.+) (.+)$")
unified_header_index = re.compile("^Index: (.+)$")
unified_header_old_line = re.compile(r"^--- " + file_timestamp_str + "$")
unified_header_new_line = re.compile(r"^\+\+\+ " + file_timestamp_str + "$")
Expand Down Expand Up @@ -68,7 +68,7 @@
cvs_header_rcs = re.compile(r"^RCS file: (.+)(?:,\w{1}$|$)")
cvs_header_timestamp = re.compile(r"(.+)\t([\d.]+)")
cvs_header_timestamp_colon = re.compile(r":([\d.]+)\t(.+)")
old_cvs_diffcmd_header = re.compile("^diff.* (.+):(.*) (.+):(.*)$")
old_cvs_diffcmd_header = re.compile("^diff(?: .+)? (.+):(.*) (.+):(.*)$")


def parse_patch(text):
Expand Down
31 changes: 31 additions & 0 deletions tests/casefiles/eclipse-attachment-1701.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
? cvsdiff
? model/org/eclipse/jdt/internal/debug/core/BreakMouseGrab.java
Index: model/org/eclipse/jdt/internal/debug/core/JDIDebugPlugin.java
===================================================================
RCS file: /home/eclipse/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/JDIDebugPlugin.java,v
retrieving revision 1.34
diff -u -p -r1.34 JDIDebugPlugin.java
--- model/org/eclipse/jdt/internal/debug/core/JDIDebugPlugin.java 6 Jun 2002 20:33:46 -0000 1.34
+++ model/org/eclipse/jdt/internal/debug/core/JDIDebugPlugin.java 16 Jul 2002 20:37:56 -0000
@@ -61,6 +61,13 @@ public class JDIDebugPlugin extends Plug
private boolean fTrace = false;

/**
+ * On SWT/GTK applications, we need to drop
+ * any mouse grabs when a breakpoint is hit
+ * or the mouse is not usable.
+ */
+ private BreakMouseGrab breakMouseGrab;
+
+ /**
* Returns whether the debug UI plug-in is in trace
* mode.
*
@@ -117,6 +124,7 @@ public class JDIDebugPlugin extends Plug
fBreakpointListeners = new ListenerList(5);
getPluginPreferences().setDefault(JDIDebugModel.PREF_REQUEST_TIMEOUT, JDIDebugModel.DEF_REQUEST_TIMEOUT);
getPluginPreferences().addPropertyChangeListener(this);
+ breakMouseGrab = new BreakMouseGrab();
}

/**
140 changes: 140 additions & 0 deletions tests/casefiles/linux-29e1dfcd5150097f32f34891c85a50d9ead19df3.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
From 29e1dfcd5150097f32f34891c85a50d9ead19df3 Mon Sep 17 00:00:00 2001
From: Lihong Kou <[email protected]>
Date: Tue, 23 Jun 2020 20:28:41 +0800
Subject: Bluetooth: add a mutex lock to avoid UAF in do_enale_set

[ Upstream commit f9c70bdc279b191da8d60777c627702c06e4a37d ]

In the case we set or free the global value listen_chan in
different threads, we can encounter the UAF problems because
the method is not protected by any lock, add one to avoid
this bug.

BUG: KASAN: use-after-free in l2cap_chan_close+0x48/0x990
net/bluetooth/l2cap_core.c:730
Read of size 8 at addr ffff888096950000 by task kworker/1:102/2868

CPU: 1 PID: 2868 Comm: kworker/1:102 Not tainted 5.5.0-syzkaller #0
Hardware name: Google Google Compute Engine/Google Compute Engine,
BIOS Google 01/01/2011
Workqueue: events do_enable_set
Call Trace:
__dump_stack lib/dump_stack.c:77 [inline]
dump_stack+0x1fb/0x318 lib/dump_stack.c:118
print_address_description+0x74/0x5c0 mm/kasan/report.c:374
__kasan_report+0x149/0x1c0 mm/kasan/report.c:506
kasan_report+0x26/0x50 mm/kasan/common.c:641
__asan_report_load8_noabort+0x14/0x20 mm/kasan/generic_report.c:135
l2cap_chan_close+0x48/0x990 net/bluetooth/l2cap_core.c:730
do_enable_set+0x660/0x900 net/bluetooth/6lowpan.c:1074
process_one_work+0x7f5/0x10f0 kernel/workqueue.c:2264
worker_thread+0xbbc/0x1630 kernel/workqueue.c:2410
kthread+0x332/0x350 kernel/kthread.c:255
ret_from_fork+0x24/0x30 arch/x86/entry/entry_64.S:352

Allocated by task 2870:
save_stack mm/kasan/common.c:72 [inline]
set_track mm/kasan/common.c:80 [inline]
__kasan_kmalloc+0x118/0x1c0 mm/kasan/common.c:515
kasan_kmalloc+0x9/0x10 mm/kasan/common.c:529
kmem_cache_alloc_trace+0x221/0x2f0 mm/slab.c:3551
kmalloc include/linux/slab.h:555 [inline]
kzalloc include/linux/slab.h:669 [inline]
l2cap_chan_create+0x50/0x320 net/bluetooth/l2cap_core.c:446
chan_create net/bluetooth/6lowpan.c:640 [inline]
bt_6lowpan_listen net/bluetooth/6lowpan.c:959 [inline]
do_enable_set+0x6a4/0x900 net/bluetooth/6lowpan.c:1078
process_one_work+0x7f5/0x10f0 kernel/workqueue.c:2264
worker_thread+0xbbc/0x1630 kernel/workqueue.c:2410
kthread+0x332/0x350 kernel/kthread.c:255
ret_from_fork+0x24/0x30 arch/x86/entry/entry_64.S:352

Freed by task 2870:
save_stack mm/kasan/common.c:72 [inline]
set_track mm/kasan/common.c:80 [inline]
kasan_set_free_info mm/kasan/common.c:337 [inline]
__kasan_slab_free+0x12e/0x1e0 mm/kasan/common.c:476
kasan_slab_free+0xe/0x10 mm/kasan/common.c:485
__cache_free mm/slab.c:3426 [inline]
kfree+0x10d/0x220 mm/slab.c:3757
l2cap_chan_destroy net/bluetooth/l2cap_core.c:484 [inline]
kref_put include/linux/kref.h:65 [inline]
l2cap_chan_put+0x170/0x190 net/bluetooth/l2cap_core.c:498
do_enable_set+0x66c/0x900 net/bluetooth/6lowpan.c:1075
process_one_work+0x7f5/0x10f0 kernel/workqueue.c:2264
worker_thread+0xbbc/0x1630 kernel/workqueue.c:2410
kthread+0x332/0x350 kernel/kthread.c:255
ret_from_fork+0x24/0x30 arch/x86/entry/entry_64.S:352

The buggy address belongs to the object at ffff888096950000
which belongs to the cache kmalloc-2k of size 2048
The buggy address is located 0 bytes inside of
2048-byte region [ffff888096950000, ffff888096950800)
The buggy address belongs to the page:
page:ffffea00025a5400 refcount:1 mapcount:0 mapping:ffff8880aa400e00 index:0x0
flags: 0xfffe0000000200(slab)
raw: 00fffe0000000200 ffffea00027d1548 ffffea0002397808 ffff8880aa400e00
raw: 0000000000000000 ffff888096950000 0000000100000001 0000000000000000
page dumped because: kasan: bad access detected

Memory state around the buggy address:
ffff88809694ff00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
ffff88809694ff80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
>ffff888096950000: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
^
ffff888096950080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff888096950100: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
==================================================================

Reported-by: [email protected]
Signed-off-by: Lihong Kou <[email protected]>
Signed-off-by: Marcel Holtmann <[email protected]>
Signed-off-by: Sasha Levin <[email protected]>
---
net/bluetooth/6lowpan.c | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
index 357475cceec61b..9a75f9b00b5129 100644
--- a/net/bluetooth/6lowpan.c
+++ b/net/bluetooth/6lowpan.c
@@ -57,6 +57,7 @@ static bool enable_6lowpan;
/* We are listening incoming connections via this channel
*/
static struct l2cap_chan *listen_chan;
+static DEFINE_MUTEX(set_lock);

struct lowpan_peer {
struct list_head list;
@@ -1082,12 +1083,14 @@ static void do_enable_set(struct work_struct *work)

enable_6lowpan = set_enable->flag;

+ mutex_lock(&set_lock);
if (listen_chan) {
l2cap_chan_close(listen_chan, 0);
l2cap_chan_put(listen_chan);
}

listen_chan = bt_6lowpan_listen();
+ mutex_unlock(&set_lock);

kfree(set_enable);
}
@@ -1139,11 +1142,13 @@ static ssize_t lowpan_control_write(struct file *fp,
if (ret == -EINVAL)
return ret;

+ mutex_lock(&set_lock);
if (listen_chan) {
l2cap_chan_close(listen_chan, 0);
l2cap_chan_put(listen_chan);
listen_chan = NULL;
}
+ mutex_unlock(&set_lock);

if (conn) {
struct lowpan_peer *peer;
--
cgit 1.2.3-korg

49 changes: 46 additions & 3 deletions tests/test_patch.py
Original file line number Diff line number Diff line change
Expand Up @@ -1390,6 +1390,7 @@ def test_apache_attachment_2241(self):
self.assert_diffs_equal(results, expected)

def test_space_in_path_header(self):
# From https://bugzillaattachments.eclipsecontent.org/bugs/attachment.cgi?id=126343
with open("tests/casefiles/eclipse-attachment-126343.header") as f:
text = f.read()

Expand Down Expand Up @@ -1426,7 +1427,8 @@ def test_svn_mixed_line_ends(self):
self.assertEqual(results[0].header, expected_header)

def test_huge_patch(self):
text_parts = ["""diff --git a/huge.file b/huge.file
text_parts = [
"""diff --git a/huge.file b/huge.file
index 0000000..1111111 100644
--- a/huge.file
+++ a/huge.file
Expand All @@ -1438,9 +1440,10 @@ def test_huge_patch(self):
-44444444
+55555555
+66666666
"""]
"""
]
text_parts.extend("+" + hex(n) + "\n" for n in range(0, 1000000))
text = ''.join(text_parts)
text = "".join(text_parts)
start_time = time.time()
result = list(wtp.patch.parse_patch(text))
self.assertEqual(1, len(result))
Expand Down Expand Up @@ -1508,6 +1511,46 @@ def test_git_bin_patch_minline(self):
== "b07b94142cfce2094b5be04e9d30b653a7c63917"
)

def test_linux_29e1dfc(self):
with open(
"tests/casefiles/linux-29e1dfcd5150097f32f34891c85a50d9ead19df3.patch"
) as f:
text = f.read()

# testing we get to the diff
path = "net/bluetooth/6lowpan.c"
expected = headerobj(
index_path=None,
old_path=path,
old_version="357475cceec61b",
new_path=path,
new_version="9a75f9b00b5129",
)

results = list(wtp.patch.parse_patch(text))
self.assertEqual(len(results), 1)
self.assertEqual(results[0].header, expected)

def test_eclipse_cvsdiff(self):
# From https://bugzillaattachments.eclipsecontent.org/bugs/attachment.cgi?id=1701
with open("tests/casefiles/eclipse-attachment-1701.patch") as f:
text = f.read()

expected = headerobj(
index_path=(
"model/org/eclipse/jdt/internal/debug/core/JDIDebugPlugin.java"
),
old_path="model/org/eclipse/jdt/internal/debug/core/JDIDebugPlugin.java",
old_version="1.34",
new_path="model/org/eclipse/jdt/internal/debug/core/JDIDebugPlugin.java",
new_version="16 Jul 2002 20:37:56 -0000",
)

results = list(wtp.patch.parse_patch(text))
self.assertEqual(len(results), 1)
self.assertEqual(results[0].header, expected)
self.assertEqual(len(results[0].changes), 20)


if __name__ == "__main__":
unittest.main()

0 comments on commit 92c1bb6

Please sign in to comment.