From 116a49dd0f90ef38c2bd8180c3aaaeae8fbc636d Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Sun, 19 Jan 2025 02:33:32 +0700 Subject: [PATCH 1/2] packing: Do use extra arguments in `p*` and `u*` --- CHANGELOG.md | 2 +- pwnlib/util/packing.py | 49 ++++++++++++++++++++++++++++++------------ 2 files changed, 36 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f809a8d24..4e6734ae7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -73,7 +73,7 @@ The table below shows which release corresponds to each branch, and what date th | [2.2.0](#220) | | Jan 5, 2015 ## 5.0.0 (`dev`) - +- [#2526][2526] Properly make use of extra arguments in `packing` utilities. ## 4.15.0 (`beta`) - [#2508][2508] Ignore a warning when compiling with asm on nix diff --git a/pwnlib/util/packing.py b/pwnlib/util/packing.py index 3503bd937..2ac847c28 100644 --- a/pwnlib/util/packing.py +++ b/pwnlib/util/packing.py @@ -332,7 +332,7 @@ def routine(data, stacklevel=None): # # Make normal user-oriented packers, e.g. p8 # -def _do_packing(op, size, number): +def _do_packing(op, size, number, endianness=None, sign=None): name = "%s%s" % (op,size) mod = sys.modules[__name__] @@ -342,8 +342,8 @@ def _do_packing(op, size, number): bs = getattr(mod, "_%sbs" % (name)) bu = getattr(mod, "_%sbu" % (name)) - endian = context.endian - signed = context.signed + endian = endianness or context.endian + signed = sign or context.signed return {("little", True ): ls, ("little", False): lu, ("big", True ): bs, @@ -365,7 +365,7 @@ def p8(number, endianness = None, sign = None, **kwargs): Returns: The packed number as a byte string """ - return _do_packing('p', 8, number) + return _do_packing('p', 8, number, endianness, sign) @LocalNoarchContext def p16(number, endianness = None, sign = None, **kwargs): @@ -382,8 +382,15 @@ def p16(number, endianness = None, sign = None, **kwargs): Returns: The packed number as a byte string + + Examples: + + >>> p16(0x4142, 'big') + b'AB' + >>> p16(0x4142, endianness='big') + b'AB' """ - return _do_packing('p', 16, number) + return _do_packing('p', 16, number, endianness, sign) @LocalNoarchContext def p32(number, endianness = None, sign = None, **kwargs): @@ -400,8 +407,15 @@ def p32(number, endianness = None, sign = None, **kwargs): Returns: The packed number as a byte string + + Examples: + + >>> p32(0x41424344, 'big') + b'ABCD' + >>> p32(0x41424344, endianness='big') + b'ABCD' """ - return _do_packing('p', 32, number) + return _do_packing('p', 32, number, endianness, sign) @LocalNoarchContext def p64(number, endianness = None, sign = None, **kwargs): @@ -418,8 +432,15 @@ def p64(number, endianness = None, sign = None, **kwargs): Returns: The packed number as a byte string + + Examples: + + >>> p64(0x4142434445464748, 'big') + b'ABCDEFGH' + >>> p64(0x4142434445464748, endianness='big') + b'ABCDEFGH' """ - return _do_packing('p', 64, number) + return _do_packing('p', 64, number, endianness, sign) @LocalNoarchContext def u8(data, endianness = None, sign = None, **kwargs): @@ -437,7 +458,7 @@ def u8(data, endianness = None, sign = None, **kwargs): Returns: The unpacked number """ - return _do_packing('u', 8, data) + return _do_packing('u', 8, data, endianness, sign) @LocalNoarchContext def u16(data, endianness = None, sign = None, **kwargs): @@ -455,7 +476,7 @@ def u16(data, endianness = None, sign = None, **kwargs): Returns: The unpacked number """ - return _do_packing('u', 16, data) + return _do_packing('u', 16, data, endianness, sign) @LocalNoarchContext def u32(data, endianness = None, sign = None, **kwargs): @@ -473,7 +494,7 @@ def u32(data, endianness = None, sign = None, **kwargs): Returns: The unpacked number """ - return _do_packing('u', 32, data) + return _do_packing('u', 32, data, endianness, sign) @LocalNoarchContext def u64(data, endianness = None, sign = None, **kwargs): @@ -491,7 +512,7 @@ def u64(data, endianness = None, sign = None, **kwargs): Returns: The unpacked number """ - return _do_packing('u', 64, data) + return _do_packing('u', 64, data, endianness, sign) def make_packer(word_size = None, sign = None, **kwargs): """make_packer(word_size = None, endianness = None, sign = None) -> number → str @@ -775,7 +796,7 @@ def flat(*args, **kwargs): Examples: (Test setup, please ignore) - + >>> context.clear() Basic usage of :meth:`flat` works similar to the pack() routines. @@ -822,7 +843,7 @@ def flat(*args, **kwargs): Dictionary usage permits directly using values derived from :func:`.cyclic`. See :func:`.cyclic`, :function:`pwnlib.context.context.cyclic_alphabet`, and :data:`.context.cyclic_size` - for more options. + for more options. The cyclic pattern can be provided as either the text or hexadecimal offset. @@ -873,7 +894,7 @@ def flat(*args, **kwargs): Negative indices are also supported, though this only works for integer keys. - + >>> flat({-4: b'x', -1: b'A', 0: b'0', 4: b'y'}) b'xaaA0aaay' """ From b25a0da35788e030539f216a98401b900480138b Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Sun, 19 Jan 2025 12:59:34 +0700 Subject: [PATCH 2/2] packing: Force keyword syntax for `sign` argument --- CHANGELOG.md | 1 + pwnlib/util/packing.py | 36 ++++++++++++++++++------------------ 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e6734ae7..dc3dfe454 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -74,6 +74,7 @@ The table below shows which release corresponds to each branch, and what date th ## 5.0.0 (`dev`) - [#2526][2526] Properly make use of extra arguments in `packing` utilities. + `sign` parameter requires keyword syntax to specify it. ## 4.15.0 (`beta`) - [#2508][2508] Ignore a warning when compiling with asm on nix diff --git a/pwnlib/util/packing.py b/pwnlib/util/packing.py index 2ac847c28..a7f03aa6d 100644 --- a/pwnlib/util/packing.py +++ b/pwnlib/util/packing.py @@ -332,7 +332,7 @@ def routine(data, stacklevel=None): # # Make normal user-oriented packers, e.g. p8 # -def _do_packing(op, size, number, endianness=None, sign=None): +def _do_packing(op, size, number, endianness=None): name = "%s%s" % (op,size) mod = sys.modules[__name__] @@ -343,14 +343,14 @@ def _do_packing(op, size, number, endianness=None, sign=None): bu = getattr(mod, "_%sbu" % (name)) endian = endianness or context.endian - signed = sign or context.signed + signed = context.signed return {("little", True ): ls, ("little", False): lu, ("big", True ): bs, ("big", False): bu}[endian, signed](number, 3) @LocalNoarchContext -def p8(number, endianness = None, sign = None, **kwargs): +def p8(number, endianness = None, **kwargs): """p8(number, endianness, sign, ...) -> bytes Packs an 8-bit integer @@ -365,10 +365,10 @@ def p8(number, endianness = None, sign = None, **kwargs): Returns: The packed number as a byte string """ - return _do_packing('p', 8, number, endianness, sign) + return _do_packing('p', 8, number, endianness) @LocalNoarchContext -def p16(number, endianness = None, sign = None, **kwargs): +def p16(number, endianness = None, **kwargs): """p16(number, endianness, sign, ...) -> bytes Packs an 16-bit integer @@ -390,10 +390,10 @@ def p16(number, endianness = None, sign = None, **kwargs): >>> p16(0x4142, endianness='big') b'AB' """ - return _do_packing('p', 16, number, endianness, sign) + return _do_packing('p', 16, number, endianness) @LocalNoarchContext -def p32(number, endianness = None, sign = None, **kwargs): +def p32(number, endianness = None, **kwargs): """p32(number, endianness, sign, ...) -> bytes Packs an 32-bit integer @@ -415,10 +415,10 @@ def p32(number, endianness = None, sign = None, **kwargs): >>> p32(0x41424344, endianness='big') b'ABCD' """ - return _do_packing('p', 32, number, endianness, sign) + return _do_packing('p', 32, number, endianness) @LocalNoarchContext -def p64(number, endianness = None, sign = None, **kwargs): +def p64(number, endianness = None, **kwargs): """p64(number, endianness, sign, ...) -> bytes Packs an 64-bit integer @@ -440,10 +440,10 @@ def p64(number, endianness = None, sign = None, **kwargs): >>> p64(0x4142434445464748, endianness='big') b'ABCDEFGH' """ - return _do_packing('p', 64, number, endianness, sign) + return _do_packing('p', 64, number, endianness) @LocalNoarchContext -def u8(data, endianness = None, sign = None, **kwargs): +def u8(data, endianness = None, **kwargs): """u8(data, endianness, sign, ...) -> int Unpacks an 8-bit integer @@ -458,10 +458,10 @@ def u8(data, endianness = None, sign = None, **kwargs): Returns: The unpacked number """ - return _do_packing('u', 8, data, endianness, sign) + return _do_packing('u', 8, data, endianness) @LocalNoarchContext -def u16(data, endianness = None, sign = None, **kwargs): +def u16(data, endianness = None, **kwargs): """u16(data, endianness, sign, ...) -> int Unpacks an 16-bit integer @@ -476,10 +476,10 @@ def u16(data, endianness = None, sign = None, **kwargs): Returns: The unpacked number """ - return _do_packing('u', 16, data, endianness, sign) + return _do_packing('u', 16, data, endianness) @LocalNoarchContext -def u32(data, endianness = None, sign = None, **kwargs): +def u32(data, endianness = None, **kwargs): """u32(data, endianness, sign, ...) -> int Unpacks an 32-bit integer @@ -494,10 +494,10 @@ def u32(data, endianness = None, sign = None, **kwargs): Returns: The unpacked number """ - return _do_packing('u', 32, data, endianness, sign) + return _do_packing('u', 32, data, endianness) @LocalNoarchContext -def u64(data, endianness = None, sign = None, **kwargs): +def u64(data, endianness = None, **kwargs): """u64(data, endianness, sign, ...) -> int Unpacks an 64-bit integer @@ -512,7 +512,7 @@ def u64(data, endianness = None, sign = None, **kwargs): Returns: The unpacked number """ - return _do_packing('u', 64, data, endianness, sign) + return _do_packing('u', 64, data, endianness) def make_packer(word_size = None, sign = None, **kwargs): """make_packer(word_size = None, endianness = None, sign = None) -> number → str