Skip to content

Commit 92c1bb6

Browse files
committed
tests, optional group for diffcmd headers, and release prep
bump for release (hopefully) fix brew install path export mac test separately bump pyproject.yaml
1 parent dadb500 commit 92c1bb6

File tree

8 files changed

+254
-27
lines changed

8 files changed

+254
-27
lines changed

.github/workflows/build.yml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
strategy:
1717
matrix:
1818
os: [ubuntu-latest, macos-latest, windows-latest]
19-
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
19+
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
2020

2121
steps:
2222
- uses: actions/checkout@v4
@@ -56,6 +56,13 @@ jobs:
5656
- name: Test
5757
run: |
5858
pytest --doctest-modules --doctest-glob='*.rst' --junitxml=junit/test-results-${{ matrix.python-version }}-${{ matrix.os }}.xml
59+
if: ${{ matrix.os != 'macos-latest' }}
60+
61+
- name: Test macos-latest
62+
run: |
63+
export PATH="/opt/homebrew/opt/gpatch/libexec/gnubin:$PATH"
64+
pytest --doctest-modules --doctest-glob='*.rst' --junitxml=junit/test-results-${{ matrix.python-version }}-${{ matrix.os }}.xml
65+
if: ${{ matrix.os == 'macos-latest' }}
5966

6067
- name: Upload pytest test results
6168
uses: actions/upload-artifact@v4

HISTORY.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
Nothing yet :)
44

5+
# 1.0.7
6+
7+
- PR #62 fix: incorrect regular expression matching diffcmd (Thanks, @jingfelix)
8+
- Support up to 3.13
9+
- Drop support up to 3.8
10+
511
# 1.0.6
612

713
- PR #60 Improve huge_patch test (Thanks, @arkamar)

pyproject.toml

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,29 @@
11
[project]
22
name = "whatthepatch"
3-
version = "1.0.6"
3+
version = "1.0.7"
44
maintainers = [{ name = "Christopher S. Corley", email = "[email protected]" }]
5-
requires-python = ">=3.8"
5+
requires-python = ">=3.9"
66
readme = "README.rst"
77
description = "A patch parsing and application library."
88
keywords = ["patch", "diff", "parser"]
99
classifiers = [
10-
"Development Status :: 5 - Production/Stable",
11-
"Intended Audience :: Developers",
12-
"Intended Audience :: Science/Research",
13-
"License :: OSI Approved :: MIT License",
14-
"Operating System :: OS Independent",
15-
"Programming Language :: Python :: 3 :: Only",
16-
"Programming Language :: Python :: 3",
17-
"Programming Language :: Python :: 3.8",
18-
"Programming Language :: Python :: 3.9",
19-
"Programming Language :: Python :: 3.10",
20-
"Programming Language :: Python :: 3.11",
21-
"Programming Language :: Python :: 3.12",
22-
"Programming Language :: Python :: Implementation :: CPython",
23-
"Topic :: Software Development :: Libraries :: Python Modules",
24-
"Topic :: Software Development :: Version Control",
25-
"Topic :: Software Development",
26-
"Topic :: Text Processing",
10+
"Development Status :: 5 - Production/Stable",
11+
"Intended Audience :: Developers",
12+
"Intended Audience :: Science/Research",
13+
"License :: OSI Approved :: MIT License",
14+
"Operating System :: OS Independent",
15+
"Programming Language :: Python :: 3 :: Only",
16+
"Programming Language :: Python :: 3",
17+
"Programming Language :: Python :: 3.9",
18+
"Programming Language :: Python :: 3.10",
19+
"Programming Language :: Python :: 3.11",
20+
"Programming Language :: Python :: 3.12",
21+
"Programming Language :: Python :: 3.13",
22+
"Programming Language :: Python :: Implementation :: CPython",
23+
"Topic :: Software Development :: Libraries :: Python Modules",
24+
"Topic :: Software Development :: Version Control",
25+
"Topic :: Software Development",
26+
"Topic :: Text Processing",
2727
]
2828

2929
[project.urls]

release.nix

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
{ lib, python3Packages, setuptools }:
22
with python3Packages;
3-
buildPythonPackage rec {
3+
buildPythonPackage {
44
pname = "whatthepatch";
5-
version = "1.0.6";
5+
version = "1.0.7";
66
format = "pyproject";
77
src = ./.;
88

src/whatthepatch/patch.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
# .+? was previously [^:\t\n\r\f\v]+
2020

2121
# general diff regex
22-
diffcmd_header = re.compile("^diff .* (.+) (.+)$")
22+
diffcmd_header = re.compile("^diff(?: .+)? (.+) (.+)$")
2323
unified_header_index = re.compile("^Index: (.+)$")
2424
unified_header_old_line = re.compile(r"^--- " + file_timestamp_str + "$")
2525
unified_header_new_line = re.compile(r"^\+\+\+ " + file_timestamp_str + "$")
@@ -68,7 +68,7 @@
6868
cvs_header_rcs = re.compile(r"^RCS file: (.+)(?:,\w{1}$|$)")
6969
cvs_header_timestamp = re.compile(r"(.+)\t([\d.]+)")
7070
cvs_header_timestamp_colon = re.compile(r":([\d.]+)\t(.+)")
71-
old_cvs_diffcmd_header = re.compile("^diff.* (.+):(.*) (.+):(.*)$")
71+
old_cvs_diffcmd_header = re.compile("^diff(?: .+)? (.+):(.*) (.+):(.*)$")
7272

7373

7474
def parse_patch(text):
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
? cvsdiff
2+
? model/org/eclipse/jdt/internal/debug/core/BreakMouseGrab.java
3+
Index: model/org/eclipse/jdt/internal/debug/core/JDIDebugPlugin.java
4+
===================================================================
5+
RCS file: /home/eclipse/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/JDIDebugPlugin.java,v
6+
retrieving revision 1.34
7+
diff -u -p -r1.34 JDIDebugPlugin.java
8+
--- model/org/eclipse/jdt/internal/debug/core/JDIDebugPlugin.java 6 Jun 2002 20:33:46 -0000 1.34
9+
+++ model/org/eclipse/jdt/internal/debug/core/JDIDebugPlugin.java 16 Jul 2002 20:37:56 -0000
10+
@@ -61,6 +61,13 @@ public class JDIDebugPlugin extends Plug
11+
private boolean fTrace = false;
12+
13+
/**
14+
+ * On SWT/GTK applications, we need to drop
15+
+ * any mouse grabs when a breakpoint is hit
16+
+ * or the mouse is not usable.
17+
+ */
18+
+ private BreakMouseGrab breakMouseGrab;
19+
+
20+
+ /**
21+
* Returns whether the debug UI plug-in is in trace
22+
* mode.
23+
*
24+
@@ -117,6 +124,7 @@ public class JDIDebugPlugin extends Plug
25+
fBreakpointListeners = new ListenerList(5);
26+
getPluginPreferences().setDefault(JDIDebugModel.PREF_REQUEST_TIMEOUT, JDIDebugModel.DEF_REQUEST_TIMEOUT);
27+
getPluginPreferences().addPropertyChangeListener(this);
28+
+ breakMouseGrab = new BreakMouseGrab();
29+
}
30+
31+
/**
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
From 29e1dfcd5150097f32f34891c85a50d9ead19df3 Mon Sep 17 00:00:00 2001
2+
From: Lihong Kou <[email protected]>
3+
Date: Tue, 23 Jun 2020 20:28:41 +0800
4+
Subject: Bluetooth: add a mutex lock to avoid UAF in do_enale_set
5+
6+
[ Upstream commit f9c70bdc279b191da8d60777c627702c06e4a37d ]
7+
8+
In the case we set or free the global value listen_chan in
9+
different threads, we can encounter the UAF problems because
10+
the method is not protected by any lock, add one to avoid
11+
this bug.
12+
13+
BUG: KASAN: use-after-free in l2cap_chan_close+0x48/0x990
14+
net/bluetooth/l2cap_core.c:730
15+
Read of size 8 at addr ffff888096950000 by task kworker/1:102/2868
16+
17+
CPU: 1 PID: 2868 Comm: kworker/1:102 Not tainted 5.5.0-syzkaller #0
18+
Hardware name: Google Google Compute Engine/Google Compute Engine,
19+
BIOS Google 01/01/2011
20+
Workqueue: events do_enable_set
21+
Call Trace:
22+
__dump_stack lib/dump_stack.c:77 [inline]
23+
dump_stack+0x1fb/0x318 lib/dump_stack.c:118
24+
print_address_description+0x74/0x5c0 mm/kasan/report.c:374
25+
__kasan_report+0x149/0x1c0 mm/kasan/report.c:506
26+
kasan_report+0x26/0x50 mm/kasan/common.c:641
27+
__asan_report_load8_noabort+0x14/0x20 mm/kasan/generic_report.c:135
28+
l2cap_chan_close+0x48/0x990 net/bluetooth/l2cap_core.c:730
29+
do_enable_set+0x660/0x900 net/bluetooth/6lowpan.c:1074
30+
process_one_work+0x7f5/0x10f0 kernel/workqueue.c:2264
31+
worker_thread+0xbbc/0x1630 kernel/workqueue.c:2410
32+
kthread+0x332/0x350 kernel/kthread.c:255
33+
ret_from_fork+0x24/0x30 arch/x86/entry/entry_64.S:352
34+
35+
Allocated by task 2870:
36+
save_stack mm/kasan/common.c:72 [inline]
37+
set_track mm/kasan/common.c:80 [inline]
38+
__kasan_kmalloc+0x118/0x1c0 mm/kasan/common.c:515
39+
kasan_kmalloc+0x9/0x10 mm/kasan/common.c:529
40+
kmem_cache_alloc_trace+0x221/0x2f0 mm/slab.c:3551
41+
kmalloc include/linux/slab.h:555 [inline]
42+
kzalloc include/linux/slab.h:669 [inline]
43+
l2cap_chan_create+0x50/0x320 net/bluetooth/l2cap_core.c:446
44+
chan_create net/bluetooth/6lowpan.c:640 [inline]
45+
bt_6lowpan_listen net/bluetooth/6lowpan.c:959 [inline]
46+
do_enable_set+0x6a4/0x900 net/bluetooth/6lowpan.c:1078
47+
process_one_work+0x7f5/0x10f0 kernel/workqueue.c:2264
48+
worker_thread+0xbbc/0x1630 kernel/workqueue.c:2410
49+
kthread+0x332/0x350 kernel/kthread.c:255
50+
ret_from_fork+0x24/0x30 arch/x86/entry/entry_64.S:352
51+
52+
Freed by task 2870:
53+
save_stack mm/kasan/common.c:72 [inline]
54+
set_track mm/kasan/common.c:80 [inline]
55+
kasan_set_free_info mm/kasan/common.c:337 [inline]
56+
__kasan_slab_free+0x12e/0x1e0 mm/kasan/common.c:476
57+
kasan_slab_free+0xe/0x10 mm/kasan/common.c:485
58+
__cache_free mm/slab.c:3426 [inline]
59+
kfree+0x10d/0x220 mm/slab.c:3757
60+
l2cap_chan_destroy net/bluetooth/l2cap_core.c:484 [inline]
61+
kref_put include/linux/kref.h:65 [inline]
62+
l2cap_chan_put+0x170/0x190 net/bluetooth/l2cap_core.c:498
63+
do_enable_set+0x66c/0x900 net/bluetooth/6lowpan.c:1075
64+
process_one_work+0x7f5/0x10f0 kernel/workqueue.c:2264
65+
worker_thread+0xbbc/0x1630 kernel/workqueue.c:2410
66+
kthread+0x332/0x350 kernel/kthread.c:255
67+
ret_from_fork+0x24/0x30 arch/x86/entry/entry_64.S:352
68+
69+
The buggy address belongs to the object at ffff888096950000
70+
which belongs to the cache kmalloc-2k of size 2048
71+
The buggy address is located 0 bytes inside of
72+
2048-byte region [ffff888096950000, ffff888096950800)
73+
The buggy address belongs to the page:
74+
page:ffffea00025a5400 refcount:1 mapcount:0 mapping:ffff8880aa400e00 index:0x0
75+
flags: 0xfffe0000000200(slab)
76+
raw: 00fffe0000000200 ffffea00027d1548 ffffea0002397808 ffff8880aa400e00
77+
raw: 0000000000000000 ffff888096950000 0000000100000001 0000000000000000
78+
page dumped because: kasan: bad access detected
79+
80+
Memory state around the buggy address:
81+
ffff88809694ff00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
82+
ffff88809694ff80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
83+
>ffff888096950000: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
84+
^
85+
ffff888096950080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
86+
ffff888096950100: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
87+
==================================================================
88+
89+
Reported-by: [email protected]
90+
Signed-off-by: Lihong Kou <[email protected]>
91+
Signed-off-by: Marcel Holtmann <[email protected]>
92+
Signed-off-by: Sasha Levin <[email protected]>
93+
---
94+
net/bluetooth/6lowpan.c | 5 +++++
95+
1 file changed, 5 insertions(+)
96+
97+
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
98+
index 357475cceec61b..9a75f9b00b5129 100644
99+
--- a/net/bluetooth/6lowpan.c
100+
+++ b/net/bluetooth/6lowpan.c
101+
@@ -57,6 +57,7 @@ static bool enable_6lowpan;
102+
/* We are listening incoming connections via this channel
103+
*/
104+
static struct l2cap_chan *listen_chan;
105+
+static DEFINE_MUTEX(set_lock);
106+
107+
struct lowpan_peer {
108+
struct list_head list;
109+
@@ -1082,12 +1083,14 @@ static void do_enable_set(struct work_struct *work)
110+
111+
enable_6lowpan = set_enable->flag;
112+
113+
+ mutex_lock(&set_lock);
114+
if (listen_chan) {
115+
l2cap_chan_close(listen_chan, 0);
116+
l2cap_chan_put(listen_chan);
117+
}
118+
119+
listen_chan = bt_6lowpan_listen();
120+
+ mutex_unlock(&set_lock);
121+
122+
kfree(set_enable);
123+
}
124+
@@ -1139,11 +1142,13 @@ static ssize_t lowpan_control_write(struct file *fp,
125+
if (ret == -EINVAL)
126+
return ret;
127+
128+
+ mutex_lock(&set_lock);
129+
if (listen_chan) {
130+
l2cap_chan_close(listen_chan, 0);
131+
l2cap_chan_put(listen_chan);
132+
listen_chan = NULL;
133+
}
134+
+ mutex_unlock(&set_lock);
135+
136+
if (conn) {
137+
struct lowpan_peer *peer;
138+
--
139+
cgit 1.2.3-korg
140+

tests/test_patch.py

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1390,6 +1390,7 @@ def test_apache_attachment_2241(self):
13901390
self.assert_diffs_equal(results, expected)
13911391

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

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

14281429
def test_huge_patch(self):
1429-
text_parts = ["""diff --git a/huge.file b/huge.file
1430+
text_parts = [
1431+
"""diff --git a/huge.file b/huge.file
14301432
index 0000000..1111111 100644
14311433
--- a/huge.file
14321434
+++ a/huge.file
@@ -1438,9 +1440,10 @@ def test_huge_patch(self):
14381440
-44444444
14391441
+55555555
14401442
+66666666
1441-
"""]
1443+
"""
1444+
]
14421445
text_parts.extend("+" + hex(n) + "\n" for n in range(0, 1000000))
1443-
text = ''.join(text_parts)
1446+
text = "".join(text_parts)
14441447
start_time = time.time()
14451448
result = list(wtp.patch.parse_patch(text))
14461449
self.assertEqual(1, len(result))
@@ -1508,6 +1511,46 @@ def test_git_bin_patch_minline(self):
15081511
== "b07b94142cfce2094b5be04e9d30b653a7c63917"
15091512
)
15101513

1514+
def test_linux_29e1dfc(self):
1515+
with open(
1516+
"tests/casefiles/linux-29e1dfcd5150097f32f34891c85a50d9ead19df3.patch"
1517+
) as f:
1518+
text = f.read()
1519+
1520+
# testing we get to the diff
1521+
path = "net/bluetooth/6lowpan.c"
1522+
expected = headerobj(
1523+
index_path=None,
1524+
old_path=path,
1525+
old_version="357475cceec61b",
1526+
new_path=path,
1527+
new_version="9a75f9b00b5129",
1528+
)
1529+
1530+
results = list(wtp.patch.parse_patch(text))
1531+
self.assertEqual(len(results), 1)
1532+
self.assertEqual(results[0].header, expected)
1533+
1534+
def test_eclipse_cvsdiff(self):
1535+
# From https://bugzillaattachments.eclipsecontent.org/bugs/attachment.cgi?id=1701
1536+
with open("tests/casefiles/eclipse-attachment-1701.patch") as f:
1537+
text = f.read()
1538+
1539+
expected = headerobj(
1540+
index_path=(
1541+
"model/org/eclipse/jdt/internal/debug/core/JDIDebugPlugin.java"
1542+
),
1543+
old_path="model/org/eclipse/jdt/internal/debug/core/JDIDebugPlugin.java",
1544+
old_version="1.34",
1545+
new_path="model/org/eclipse/jdt/internal/debug/core/JDIDebugPlugin.java",
1546+
new_version="16 Jul 2002 20:37:56 -0000",
1547+
)
1548+
1549+
results = list(wtp.patch.parse_patch(text))
1550+
self.assertEqual(len(results), 1)
1551+
self.assertEqual(results[0].header, expected)
1552+
self.assertEqual(len(results[0].changes), 20)
1553+
15111554

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

0 commit comments

Comments
 (0)