From 320a56144fa5228562c2211b29754ce18690c4e2 Mon Sep 17 00:00:00 2001 From: Marian Beermann Date: Tue, 3 Jan 2017 17:38:18 +0100 Subject: [PATCH] helpers.Buffer: raise OSError subclass if too much memory is allocd --- borg/helpers.py | 14 ++++++++++++-- borg/testsuite/helpers.py | 4 ++-- borg/xattr.py | 9 +++------ 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/borg/helpers.py b/borg/helpers.py index b38ec9455..7c4a0fa91 100644 --- a/borg/helpers.py +++ b/borg/helpers.py @@ -55,9 +55,15 @@ class Error(Exception): # show a traceback? traceback = False + def __init__(self, *args): + super().__init__(*args) + self.args = args + def get_message(self): return type(self).__doc__.format(*self.args) + __str__ = get_message + class ErrorWithTraceback(Error): """like Error, but show a traceback also""" @@ -699,6 +705,10 @@ class Buffer: """ provide a thread-local buffer """ + + class MemoryLimitExceeded(Error, OSError): + """Requested buffer size {} is above the limit of {}.""" + def __init__(self, allocator, size=4096, limit=None): """ Initialize the buffer: use allocator(size) call to allocate a buffer. @@ -718,11 +728,11 @@ class Buffer: """ resize the buffer - to avoid frequent reallocation, we usually always grow (if needed). giving init=True it is possible to first-time initialize or shrink the buffer. - if a buffer size beyond the limit is requested, raise ValueError. + if a buffer size beyond the limit is requested, raise Buffer.MemoryLimitExceeded (OSError). """ size = int(size) if self.limit is not None and size > self.limit: - raise ValueError('Requested buffer size %d is above the limit of %d.' % (size, self.limit)) + raise Buffer.MemoryLimitExceeded(size, self.limit) if init or len(self) < size: self._thread_local.buffer = self.allocator(size) diff --git a/borg/testsuite/helpers.py b/borg/testsuite/helpers.py index 47d49f999..3f9c70969 100644 --- a/borg/testsuite/helpers.py +++ b/borg/testsuite/helpers.py @@ -793,7 +793,7 @@ class TestBuffer: buffer = Buffer(bytearray, size=100, limit=200) buffer.resize(200) assert len(buffer) == 200 - with pytest.raises(ValueError): + with pytest.raises(Buffer.MemoryLimitExceeded): buffer.resize(201) assert len(buffer) == 200 @@ -807,7 +807,7 @@ class TestBuffer: b3 = buffer.get(200) assert len(b3) == 200 assert b3 is not b2 # new, resized buffer - with pytest.raises(ValueError): + with pytest.raises(Buffer.MemoryLimitExceeded): buffer.get(201) # beyond limit assert len(buffer) == 200 diff --git a/borg/xattr.py b/borg/xattr.py index 0c1e9f0eb..75cb91890 100644 --- a/borg/xattr.py +++ b/borg/xattr.py @@ -10,7 +10,7 @@ from ctypes import CDLL, create_string_buffer, c_ssize_t, c_size_t, c_char_p, c_ from ctypes.util import find_library from distutils.version import LooseVersion -from .helpers import Buffer, Error +from .helpers import Buffer try: @@ -113,11 +113,8 @@ def split_lstring(buf): return result -class BufferTooSmallError(OSError): - """insufficient buffer memory for completing a xattr operation.""" - - def __str__(self): - return self.__doc__ +class BufferTooSmallError(Exception): + """the buffer given to an xattr function was too small for the result.""" def _check(rv, path=None, detect_buffer_too_small=False):