Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 28de0a70fa | |||
| 71119bb049 |
@ -1 +0,0 @@
|
|||||||
aa08a912bb560aa6def7b29d91ac6198a6b077f3 SOURCES/v1.0.6.tar.gz
|
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
@ -1 +1 @@
|
|||||||
SOURCES/v1.0.6.tar.gz
|
brotli-1.1.0.tar.gz
|
||||||
|
|||||||
447
CVE-2025-6176-brotli-1234.patch
Normal file
447
CVE-2025-6176-brotli-1234.patch
Normal file
@ -0,0 +1,447 @@
|
|||||||
|
From 28ce91caf605ac5481e9ca69131a28e1087574b7 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Robert Obryk <robryk@google.com>
|
||||||
|
Date: Tue, 17 Sep 2024 16:50:39 +0200
|
||||||
|
Subject: [PATCH 1/2] add size limit to buffer
|
||||||
|
|
||||||
|
---
|
||||||
|
python/_brotli.c | 32 +++++++++++++++++++++++---------
|
||||||
|
1 file changed, 23 insertions(+), 9 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/python/_brotli.c b/python/_brotli.c
|
||||||
|
index c6a0da03d..75c54c489 100644
|
||||||
|
--- a/python/_brotli.c
|
||||||
|
+++ b/python/_brotli.c
|
||||||
|
@@ -23,6 +23,7 @@ typedef struct {
|
||||||
|
PyObject *list;
|
||||||
|
/* Number of whole allocated size. */
|
||||||
|
Py_ssize_t allocated;
|
||||||
|
+ Py_ssize_t size_limit;
|
||||||
|
} BlocksOutputBuffer;
|
||||||
|
|
||||||
|
static const char unable_allocate_msg[] = "Unable to allocate output buffer.";
|
||||||
|
@@ -69,11 +70,17 @@ static const Py_ssize_t BUFFER_BLOCK_SIZE[] =
|
||||||
|
Return -1 on failure
|
||||||
|
*/
|
||||||
|
static inline int
|
||||||
|
-BlocksOutputBuffer_InitAndGrow(BlocksOutputBuffer *buffer,
|
||||||
|
+BlocksOutputBuffer_InitAndGrow(BlocksOutputBuffer *buffer, Py_ssize_t size_limit,
|
||||||
|
size_t *avail_out, uint8_t **next_out)
|
||||||
|
{
|
||||||
|
PyObject *b;
|
||||||
|
- const Py_ssize_t block_size = BUFFER_BLOCK_SIZE[0];
|
||||||
|
+ Py_ssize_t block_size = BUFFER_BLOCK_SIZE[0];
|
||||||
|
+
|
||||||
|
+ assert(size_limit > 0);
|
||||||
|
+
|
||||||
|
+ if (size_limit < block_size) {
|
||||||
|
+ block_size = size_limit;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
// Ensure .list was set to NULL, for BlocksOutputBuffer_OnError().
|
||||||
|
assert(buffer->list == NULL);
|
||||||
|
@@ -94,6 +101,7 @@ BlocksOutputBuffer_InitAndGrow(BlocksOutputBuffer *buffer,
|
||||||
|
|
||||||
|
// Set variables
|
||||||
|
buffer->allocated = block_size;
|
||||||
|
+ buffer->size_limit = size_limit;
|
||||||
|
|
||||||
|
*avail_out = (size_t) block_size;
|
||||||
|
*next_out = (uint8_t*) PyBytes_AS_STRING(b);
|
||||||
|
@@ -122,10 +130,16 @@ BlocksOutputBuffer_Grow(BlocksOutputBuffer *buffer,
|
||||||
|
block_size = BUFFER_BLOCK_SIZE[Py_ARRAY_LENGTH(BUFFER_BLOCK_SIZE) - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
- // Check buffer->allocated overflow
|
||||||
|
- if (block_size > PY_SSIZE_T_MAX - buffer->allocated) {
|
||||||
|
- PyErr_SetString(PyExc_MemoryError, unable_allocate_msg);
|
||||||
|
- return -1;
|
||||||
|
+ if (block_size > buffer->size_limit - buffer->allocated) {
|
||||||
|
+ block_size = buffer->size_limit - buffer->allocated;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (block_size == 0) {
|
||||||
|
+ // We are at the size_limit (either the provided one, in which case we
|
||||||
|
+ // shouldn't have been called, or the implicit PY_SSIZE_T_MAX one, in
|
||||||
|
+ // which case we wouldn't be able to concatenate the blocks at the end).
|
||||||
|
+ PyErr_SetString(PyExc_MemoryError, "too long");
|
||||||
|
+ return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the block
|
||||||
|
@@ -291,7 +305,7 @@ static PyObject* compress_stream(BrotliEncoderState* enc, BrotliEncoderOperation
|
||||||
|
BlocksOutputBuffer buffer = {.list=NULL};
|
||||||
|
PyObject *ret;
|
||||||
|
|
||||||
|
- if (BlocksOutputBuffer_InitAndGrow(&buffer, &available_out, &next_out) < 0) {
|
||||||
|
+ if (BlocksOutputBuffer_InitAndGrow(&buffer, PY_SSIZE_T_MAX, &available_out, &next_out) < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -604,7 +618,7 @@ static PyObject* decompress_stream(BrotliDecoderState* dec,
|
||||||
|
BlocksOutputBuffer buffer = {.list=NULL};
|
||||||
|
PyObject *ret;
|
||||||
|
|
||||||
|
- if (BlocksOutputBuffer_InitAndGrow(&buffer, &available_out, &next_out) < 0) {
|
||||||
|
+ if (BlocksOutputBuffer_InitAndGrow(&buffer, PY_SSIZE_T_MAX, &available_out, &next_out) < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -877,7 +891,7 @@ static PyObject* brotli_decompress(PyObject *self, PyObject *args, PyObject *key
|
||||||
|
next_in = (uint8_t*) input.buf;
|
||||||
|
available_in = input.len;
|
||||||
|
|
||||||
|
- if (BlocksOutputBuffer_InitAndGrow(&buffer, &available_out, &next_out) < 0) {
|
||||||
|
+ if (BlocksOutputBuffer_InitAndGrow(&buffer, PY_SSIZE_T_MAX, &available_out, &next_out) < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
From eb3a31e2d356d5a633de995afe7fe60e590a26d8 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Robert Obryk <robryk@google.com>
|
||||||
|
Date: Wed, 18 Sep 2024 15:25:06 +0200
|
||||||
|
Subject: [PATCH 2/2] add max_length to Python streaming decompression
|
||||||
|
|
||||||
|
---
|
||||||
|
python/_brotli.c | 192 ++++++++++++++++--------
|
||||||
|
python/tests/decompressor_test.py | 42 ++++++
|
||||||
|
tests/testdata/zerosukkanooa | Bin 0 -> 262263 bytes
|
||||||
|
tests/testdata/zerosukkanooa.compressed | Bin 0 -> 107 bytes
|
||||||
|
4 files changed, 175 insertions(+), 59 deletions(-)
|
||||||
|
create mode 100644 tests/testdata/zerosukkanooa
|
||||||
|
create mode 100644 tests/testdata/zerosukkanooa.compressed
|
||||||
|
|
||||||
|
diff --git a/python/_brotli.c b/python/_brotli.c
|
||||||
|
index 75c54c489..f86b04f93 100644
|
||||||
|
--- a/python/_brotli.c
|
||||||
|
+++ b/python/_brotli.c
|
||||||
|
@@ -606,57 +606,6 @@ static PyTypeObject brotli_CompressorType = {
|
||||||
|
brotli_Compressor_new, /* tp_new */
|
||||||
|
};
|
||||||
|
|
||||||
|
-static PyObject* decompress_stream(BrotliDecoderState* dec,
|
||||||
|
- uint8_t* input, size_t input_length) {
|
||||||
|
- BrotliDecoderResult result;
|
||||||
|
-
|
||||||
|
- size_t available_in = input_length;
|
||||||
|
- const uint8_t* next_in = input;
|
||||||
|
-
|
||||||
|
- size_t available_out;
|
||||||
|
- uint8_t* next_out;
|
||||||
|
- BlocksOutputBuffer buffer = {.list=NULL};
|
||||||
|
- PyObject *ret;
|
||||||
|
-
|
||||||
|
- if (BlocksOutputBuffer_InitAndGrow(&buffer, PY_SSIZE_T_MAX, &available_out, &next_out) < 0) {
|
||||||
|
- goto error;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- while (1) {
|
||||||
|
- Py_BEGIN_ALLOW_THREADS
|
||||||
|
- result = BrotliDecoderDecompressStream(dec,
|
||||||
|
- &available_in, &next_in,
|
||||||
|
- &available_out, &next_out, NULL);
|
||||||
|
- Py_END_ALLOW_THREADS
|
||||||
|
-
|
||||||
|
- if (result == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) {
|
||||||
|
- if (available_out == 0) {
|
||||||
|
- if (BlocksOutputBuffer_Grow(&buffer, &available_out, &next_out) < 0) {
|
||||||
|
- goto error;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- continue;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- break;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (result == BROTLI_DECODER_RESULT_ERROR || available_in != 0) {
|
||||||
|
- goto error;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- ret = BlocksOutputBuffer_Finish(&buffer, available_out);
|
||||||
|
- if (ret != NULL) {
|
||||||
|
- goto finally;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
-error:
|
||||||
|
- BlocksOutputBuffer_OnError(&buffer);
|
||||||
|
- ret = NULL;
|
||||||
|
-finally:
|
||||||
|
- return ret;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
PyDoc_STRVAR(brotli_Decompressor_doc,
|
||||||
|
"An object to decompress a byte string.\n"
|
||||||
|
"\n"
|
||||||
|
@@ -669,10 +618,14 @@ PyDoc_STRVAR(brotli_Decompressor_doc,
|
||||||
|
typedef struct {
|
||||||
|
PyObject_HEAD
|
||||||
|
BrotliDecoderState* dec;
|
||||||
|
+ uint8_t* unconsumed_data;
|
||||||
|
+ size_t unconsumed_data_length;
|
||||||
|
} brotli_Decompressor;
|
||||||
|
|
||||||
|
static void brotli_Decompressor_dealloc(brotli_Decompressor* self) {
|
||||||
|
BrotliDecoderDestroyInstance(self->dec);
|
||||||
|
+ if (self->unconsumed_data)
|
||||||
|
+ free(self->unconsumed_data);
|
||||||
|
#if PY_MAJOR_VERSION >= 3
|
||||||
|
Py_TYPE(self)->tp_free((PyObject*)self);
|
||||||
|
#else
|
||||||
|
@@ -688,6 +641,9 @@ static PyObject* brotli_Decompressor_new(PyTypeObject *type, PyObject *args, PyO
|
||||||
|
self->dec = BrotliDecoderCreateInstance(0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ self->unconsumed_data = NULL;
|
||||||
|
+ self->unconsumed_data_length = 0;
|
||||||
|
+
|
||||||
|
return (PyObject *)self;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -706,6 +662,79 @@ static int brotli_Decompressor_init(brotli_Decompressor *self, PyObject *args, P
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static PyObject* decompress_stream(brotli_Decompressor* self,
|
||||||
|
+ uint8_t* input, size_t input_length, Py_ssize_t max_output_length) {
|
||||||
|
+ BrotliDecoderResult result;
|
||||||
|
+
|
||||||
|
+ size_t available_in = input_length;
|
||||||
|
+ const uint8_t* next_in = input;
|
||||||
|
+
|
||||||
|
+ size_t available_out;
|
||||||
|
+ uint8_t* next_out;
|
||||||
|
+ uint8_t* new_tail;
|
||||||
|
+ BlocksOutputBuffer buffer = {.list=NULL};
|
||||||
|
+ PyObject *ret;
|
||||||
|
+
|
||||||
|
+ if (BlocksOutputBuffer_InitAndGrow(&buffer, max_output_length, &available_out, &next_out) < 0) {
|
||||||
|
+ goto error;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ while (1) {
|
||||||
|
+ Py_BEGIN_ALLOW_THREADS
|
||||||
|
+ result = BrotliDecoderDecompressStream(self->dec,
|
||||||
|
+ &available_in, &next_in,
|
||||||
|
+ &available_out, &next_out, NULL);
|
||||||
|
+ Py_END_ALLOW_THREADS
|
||||||
|
+
|
||||||
|
+ if (result == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) {
|
||||||
|
+ if (available_out == 0) {
|
||||||
|
+ if (buffer.allocated == PY_SSIZE_T_MAX) {
|
||||||
|
+ PyErr_SetString(PyExc_MemoryError, unable_allocate_msg);
|
||||||
|
+ goto error;
|
||||||
|
+ }
|
||||||
|
+ if (buffer.allocated == max_output_length) {
|
||||||
|
+ // We've reached the output length limit.
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ if (BlocksOutputBuffer_Grow(&buffer, &available_out, &next_out) < 0) {
|
||||||
|
+ goto error;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (result == BROTLI_DECODER_RESULT_ERROR || available_in != 0) {
|
||||||
|
+ available_in = 0;
|
||||||
|
+ goto error;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = BlocksOutputBuffer_Finish(&buffer, available_out);
|
||||||
|
+ if (ret != NULL) {
|
||||||
|
+ goto finally;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+error:
|
||||||
|
+ BlocksOutputBuffer_OnError(&buffer);
|
||||||
|
+ ret = NULL;
|
||||||
|
+
|
||||||
|
+finally:
|
||||||
|
+ new_tail = available_in > 0 ? malloc(available_in) : NULL;
|
||||||
|
+ if (available_in > 0) {
|
||||||
|
+ memcpy(new_tail, next_in, available_in);
|
||||||
|
+ }
|
||||||
|
+ if (self->unconsumed_data) {
|
||||||
|
+ free(self->unconsumed_data);
|
||||||
|
+ }
|
||||||
|
+ self->unconsumed_data = new_tail;
|
||||||
|
+ self->unconsumed_data_length = available_in;
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
PyDoc_STRVAR(brotli_Decompressor_process_doc,
|
||||||
|
"Process \"string\" for decompression, returning a string that contains \n"
|
||||||
|
"decompressed output data. This data should be concatenated to the output \n"
|
||||||
|
@@ -713,28 +742,38 @@ PyDoc_STRVAR(brotli_Decompressor_process_doc,
|
||||||
|
"Some or all of the input may be kept in internal buffers for later \n"
|
||||||
|
"processing, and the decompressed output data may be empty until enough input \n"
|
||||||
|
"has been accumulated.\n"
|
||||||
|
+"If max_output_length is set, no more than max_output_length bytes will be\n"
|
||||||
|
+"returned. If the limit is reached, further calls to process (potentially with\n"
|
||||||
|
+"empty input) will continue to yield more data. If, after returning a string of\n"
|
||||||
|
+"the length equal to limit, can_accept_more_data() returns False, process()\n"
|
||||||
|
+"must only be called with empty input until can_accept_more_data() once again\n"
|
||||||
|
+"returns True.\n"
|
||||||
|
"\n"
|
||||||
|
"Signature:\n"
|
||||||
|
-" decompress(string)\n"
|
||||||
|
+" decompress(string, max_output_length=int)\n"
|
||||||
|
"\n"
|
||||||
|
"Args:\n"
|
||||||
|
" string (bytes): The input data\n"
|
||||||
|
-"\n"
|
||||||
|
-"Returns:\n"
|
||||||
|
+"\n""Returns:\n"
|
||||||
|
" The decompressed output data (bytes)\n"
|
||||||
|
"\n"
|
||||||
|
"Raises:\n"
|
||||||
|
" brotli.error: If decompression fails\n");
|
||||||
|
|
||||||
|
-static PyObject* brotli_Decompressor_process(brotli_Decompressor *self, PyObject *args) {
|
||||||
|
+static PyObject* brotli_Decompressor_process(brotli_Decompressor *self, PyObject *args, PyObject* keywds) {
|
||||||
|
PyObject* ret;
|
||||||
|
Py_buffer input;
|
||||||
|
int ok;
|
||||||
|
+ Py_ssize_t max_output_length = PY_SSIZE_T_MAX;
|
||||||
|
+ uint8_t* data;
|
||||||
|
+ size_t data_length;
|
||||||
|
+
|
||||||
|
+ static char* kwlist[] = { "", "max_output_length", NULL };
|
||||||
|
|
||||||
|
#if PY_MAJOR_VERSION >= 3
|
||||||
|
- ok = PyArg_ParseTuple(args, "y*:process", &input);
|
||||||
|
+ ok = PyArg_ParseTupleAndKeywords(args, keywds, "y*|n:process", kwlist, &input, &max_output_length);
|
||||||
|
#else
|
||||||
|
- ok = PyArg_ParseTuple(args, "s*:process", &input);
|
||||||
|
+ ok = PyArg_ParseTupleAndKeywords(args, keywds, "s*|n:process", kwlist, &input, &max_output_length);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!ok) {
|
||||||
|
@@ -745,7 +784,20 @@ static PyObject* brotli_Decompressor_process(brotli_Decompressor *self, PyObject
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
- ret = decompress_stream(self->dec, (uint8_t*) input.buf, input.len);
|
||||||
|
+ if (self->unconsumed_data_length > 0) {
|
||||||
|
+ if (input.len > 0) {
|
||||||
|
+ PyErr_SetString(BrotliError, "process called with data when accept_more_data is False");
|
||||||
|
+ ret = NULL;
|
||||||
|
+ goto finally;
|
||||||
|
+ }
|
||||||
|
+ data = self->unconsumed_data;
|
||||||
|
+ data_length = self->unconsumed_data_length;
|
||||||
|
+ } else {
|
||||||
|
+ data = (uint8_t*)input.buf;
|
||||||
|
+ data_length = input.len;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = decompress_stream(self, data, data_length, max_output_length);
|
||||||
|
if (ret != NULL) {
|
||||||
|
goto finally;
|
||||||
|
}
|
||||||
|
@@ -787,13 +839,35 @@ static PyObject* brotli_Decompressor_is_finished(brotli_Decompressor *self) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+PyDoc_STRVAR(brotli_Decompressor_can_accept_more_data_doc,
|
||||||
|
+"Checks if the decoder instance can accept more compressed data. If the decompress()\n"
|
||||||
|
+"method on this instance of decompressor was never called with max_length,\n"
|
||||||
|
+"this method will always return True.\n"
|
||||||
|
+"\n"
|
||||||
|
+"Signature:"
|
||||||
|
+" can_accept_more_data()\n"
|
||||||
|
+"\n"
|
||||||
|
+"Returns:\n"
|
||||||
|
+" True if the decoder is ready to accept more compressed data via decompress()\n"
|
||||||
|
+" False if the decoder needs to output some data via decompress(b'') before\n"
|
||||||
|
+" being provided any more compressed data\n");
|
||||||
|
+
|
||||||
|
+static PyObject* brotli_Decompressor_can_accept_more_data(brotli_Decompressor* self) {
|
||||||
|
+ if (self->unconsumed_data_length > 0) {
|
||||||
|
+ Py_RETURN_FALSE;
|
||||||
|
+ } else {
|
||||||
|
+ Py_RETURN_TRUE;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static PyMemberDef brotli_Decompressor_members[] = {
|
||||||
|
{NULL} /* Sentinel */
|
||||||
|
};
|
||||||
|
|
||||||
|
static PyMethodDef brotli_Decompressor_methods[] = {
|
||||||
|
- {"process", (PyCFunction)brotli_Decompressor_process, METH_VARARGS, brotli_Decompressor_process_doc},
|
||||||
|
+ {"process", (PyCFunction)brotli_Decompressor_process, METH_VARARGS | METH_KEYWORDS, brotli_Decompressor_process_doc},
|
||||||
|
{"is_finished", (PyCFunction)brotli_Decompressor_is_finished, METH_NOARGS, brotli_Decompressor_is_finished_doc},
|
||||||
|
+ {"can_accept_more_data", (PyCFunction)brotli_Decompressor_can_accept_more_data, METH_NOARGS, brotli_Decompressor_can_accept_more_data_doc},
|
||||||
|
{NULL} /* Sentinel */
|
||||||
|
};
|
||||||
|
|
||||||
|
diff --git a/python/tests/decompressor_test.py b/python/tests/decompressor_test.py
|
||||||
|
index 05918ada8..09a76f3ee 100644
|
||||||
|
--- a/python/tests/decompressor_test.py
|
||||||
|
+++ b/python/tests/decompressor_test.py
|
||||||
|
@@ -4,6 +4,7 @@
|
||||||
|
# See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
|
import functools
|
||||||
|
+import os
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from . import _test_utils
|
||||||
|
@@ -39,10 +40,51 @@ def _decompress(self, test_data):
|
||||||
|
out_file.write(self.decompressor.process(data))
|
||||||
|
self.assertTrue(self.decompressor.is_finished())
|
||||||
|
|
||||||
|
+ def _decompress_with_limit(self, test_data, max_output_length):
|
||||||
|
+ temp_uncompressed = _test_utils.get_temp_uncompressed_name(test_data)
|
||||||
|
+ with open(temp_uncompressed, 'wb') as out_file:
|
||||||
|
+ with open(test_data, 'rb') as in_file:
|
||||||
|
+ chunk_iter = iter(functools.partial(in_file.read, 10 * 1024), b'')
|
||||||
|
+ while not self.decompressor.is_finished():
|
||||||
|
+ data = b''
|
||||||
|
+ if self.decompressor.can_accept_more_data():
|
||||||
|
+ data = next(chunk_iter, b'')
|
||||||
|
+ decompressed_data = self.decompressor.process(data, max_output_length=max_output_length)
|
||||||
|
+ self.assertTrue(len(decompressed_data) <= max_output_length)
|
||||||
|
+ out_file.write(decompressed_data)
|
||||||
|
+ self.assertTrue(next(chunk_iter, None) == None)
|
||||||
|
+
|
||||||
|
def _test_decompress(self, test_data):
|
||||||
|
self._decompress(test_data)
|
||||||
|
self._check_decompression(test_data)
|
||||||
|
|
||||||
|
+ def _test_decompress_with_limit(self, test_data):
|
||||||
|
+ self._decompress_with_limit(test_data, max_output_length=20)
|
||||||
|
+ self._check_decompression(test_data)
|
||||||
|
+
|
||||||
|
+ def test_too_much_input(self):
|
||||||
|
+ with open(os.path.join(_test_utils.TESTDATA_DIR, "zerosukkanooa.compressed"), 'rb') as in_file:
|
||||||
|
+ compressed = in_file.read()
|
||||||
|
+ self.decompressor.process(compressed[:-1], max_output_length=1)
|
||||||
|
+ # the following assertion checks whether the test setup is correct
|
||||||
|
+ self.assertTrue(not self.decompressor.can_accept_more_data())
|
||||||
|
+ with self.assertRaises(brotli.error):
|
||||||
|
+ self.decompressor.process(compressed[-1:])
|
||||||
|
+
|
||||||
|
+ def test_changing_limit(self):
|
||||||
|
+ test_data = os.path.join(_test_utils.TESTDATA_DIR, "zerosukkanooa.compressed")
|
||||||
|
+ temp_uncompressed = _test_utils.get_temp_uncompressed_name(test_data)
|
||||||
|
+ with open(temp_uncompressed, 'wb') as out_file:
|
||||||
|
+ with open(test_data, 'rb') as in_file:
|
||||||
|
+ compressed = in_file.read()
|
||||||
|
+ uncompressed = self.decompressor.process(compressed[:-1], max_output_length=1)
|
||||||
|
+ self.assertTrue(len(uncompressed) <= 1)
|
||||||
|
+ out_file.write(uncompressed)
|
||||||
|
+ while not self.decompressor.can_accept_more_data():
|
||||||
|
+ out_file.write(self.decompressor.process(b''))
|
||||||
|
+ out_file.write(self.decompressor.process(compressed[-1:]))
|
||||||
|
+ self._check_decompression(test_data)
|
||||||
|
+
|
||||||
|
def test_garbage_appended(self):
|
||||||
|
with self.assertRaises(brotli.error):
|
||||||
|
self.decompressor.process(brotli.compress(b'a') + b'a')
|
||||||
14
RHEL-32153-kBrotliBitMask-bounds.patch
Normal file
14
RHEL-32153-kBrotliBitMask-bounds.patch
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
--- brotli-1.1.0/c/dec/bit_reader.h.RHEL-32153-kBrotliBitMask-bounds 2023-08-29 13:00:29.000000000 +0200
|
||||||
|
+++ brotli-1.1.0/c/dec/bit_reader.h 2024-09-11 13:38:21.608972528 +0200
|
||||||
|
@@ -32,8 +32,10 @@ static BROTLI_INLINE brotli_reg_t BitMas
|
||||||
|
/* Masking with this expression turns to a single
|
||||||
|
"Unsigned Bit Field Extract" UBFX instruction on ARM. */
|
||||||
|
return ~(~((brotli_reg_t)0) << n);
|
||||||
|
- } else {
|
||||||
|
+ } else if (n < 33) {
|
||||||
|
return kBrotliBitMask[n];
|
||||||
|
+ } else {
|
||||||
|
+ return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,207 +0,0 @@
|
|||||||
%if 0%{?rhel} > 7
|
|
||||||
# Disable python2 build by default
|
|
||||||
%bcond_with python2
|
|
||||||
%else
|
|
||||||
%bcond_without python2
|
|
||||||
%endif
|
|
||||||
|
|
||||||
Name: brotli
|
|
||||||
Version: 1.0.6
|
|
||||||
Release: 4%{?dist}
|
|
||||||
Summary: Lossless compression algorithm
|
|
||||||
|
|
||||||
License: MIT
|
|
||||||
URL: https://github.com/google/brotli
|
|
||||||
Source0: https://github.com/google/brotli/archive/v%{version}.tar.gz
|
|
||||||
|
|
||||||
Patch1: rhbz1881156.patch
|
|
||||||
Patch2: CVE-2025-6176.patch
|
|
||||||
|
|
||||||
%if %{with python2}
|
|
||||||
BuildRequires: python2-devel
|
|
||||||
%endif
|
|
||||||
BuildRequires: python3-devel
|
|
||||||
BuildRequires: gcc-c++ gcc cmake
|
|
||||||
|
|
||||||
%description
|
|
||||||
Brotli is a generic-purpose lossless compression algorithm that compresses
|
|
||||||
data using a combination of a modern variant of the LZ77 algorithm, Huffman
|
|
||||||
coding and 2nd order context modeling, with a compression ratio comparable
|
|
||||||
to the best currently available general-purpose compression methods.
|
|
||||||
It is similar in speed with deflate but offers more dense compression.
|
|
||||||
|
|
||||||
%if %{with python2}
|
|
||||||
%package -n python2-%{name}
|
|
||||||
Summary: Lossless compression algorithm (python 2)
|
|
||||||
Requires: python2
|
|
||||||
%{?python_provide:%python_provide python2-%{name}}
|
|
||||||
|
|
||||||
%description -n python2-%{name}
|
|
||||||
Brotli is a generic-purpose lossless compression algorithm that compresses
|
|
||||||
data using a combination of a modern variant of the LZ77 algorithm, Huffman
|
|
||||||
coding and 2nd order context modeling, with a compression ratio comparable
|
|
||||||
to the best currently available general-purpose compression methods.
|
|
||||||
It is similar in speed with deflate but offers more dense compression.
|
|
||||||
This package installs a Python 2 module.
|
|
||||||
%endif
|
|
||||||
|
|
||||||
%package -n python3-%{name}
|
|
||||||
Requires: %{__python3}
|
|
||||||
Summary: Lossless compression algorithm (python 3)
|
|
||||||
%{?python_provide:%python_provide python3-%{name}}
|
|
||||||
|
|
||||||
%description -n python3-%{name}
|
|
||||||
Brotli is a generic-purpose lossless compression algorithm that compresses
|
|
||||||
data using a combination of a modern variant of the LZ77 algorithm, Huffman
|
|
||||||
coding and 2nd order context modeling, with a compression ratio comparable
|
|
||||||
to the best currently available general-purpose compression methods.
|
|
||||||
It is similar in speed with deflate but offers more dense compression.
|
|
||||||
This package installs a Python 3 module.
|
|
||||||
|
|
||||||
|
|
||||||
%package -n %{name}-devel
|
|
||||||
Summary: Lossless compression algorithm (development files)
|
|
||||||
Requires: %{name}%{?_isa} = %{version}-%{release}
|
|
||||||
|
|
||||||
%description -n %{name}-devel
|
|
||||||
Brotli is a generic-purpose lossless compression algorithm that compresses
|
|
||||||
data using a combination of a modern variant of the LZ77 algorithm, Huffman
|
|
||||||
coding and 2nd order context modeling, with a compression ratio comparable
|
|
||||||
to the best currently available general-purpose compression methods.
|
|
||||||
It is similar in speed with deflate but offers more dense compression.
|
|
||||||
This package installs the development files
|
|
||||||
|
|
||||||
%prep
|
|
||||||
%autosetup -p1 -S git
|
|
||||||
# fix permissions for -debuginfo
|
|
||||||
# rpmlint will complain if I create an extra %%files section for
|
|
||||||
# -debuginfo for this so we'll put it here instead
|
|
||||||
%{__chmod} 644 c/enc/*.[ch]
|
|
||||||
%{__chmod} 644 c/include/brotli/*.h
|
|
||||||
%{__chmod} 644 c/tools/brotli.c
|
|
||||||
|
|
||||||
%build
|
|
||||||
|
|
||||||
mkdir -p build
|
|
||||||
cd build
|
|
||||||
%cmake .. -DCMAKE_INSTALL_PREFIX="%{_prefix}" \
|
|
||||||
-DCMAKE_INSTALL_LIBDIR="%{_libdir}"
|
|
||||||
%make_build
|
|
||||||
cd ..
|
|
||||||
%if %{with python2}
|
|
||||||
%py2_build
|
|
||||||
%endif
|
|
||||||
%py3_build
|
|
||||||
|
|
||||||
%install
|
|
||||||
cd build
|
|
||||||
%make_install
|
|
||||||
|
|
||||||
# I couldn't find the option to not build the static libraries
|
|
||||||
%__rm "%{buildroot}%{_libdir}/"*.a
|
|
||||||
|
|
||||||
cd ..
|
|
||||||
# Must do the python2 install first because the scripts in /usr/bin are
|
|
||||||
# overwritten with every setup.py install, and in general we want the
|
|
||||||
# python3 version to be the default. If, however, we're installing separate
|
|
||||||
# executables for python2 and python3, the order needs to be reversed so
|
|
||||||
# the unversioned executable is the python2 one.
|
|
||||||
%if %{with python2}
|
|
||||||
%py2_install
|
|
||||||
%endif
|
|
||||||
%py3_install
|
|
||||||
%{__install} -dm755 "%{buildroot}%{_mandir}/man3"
|
|
||||||
cd docs
|
|
||||||
for i in *.3;do
|
|
||||||
%{__install} -m644 "$i" "%{buildroot}%{_mandir}/man3/${i}brotli"
|
|
||||||
done
|
|
||||||
|
|
||||||
%ldconfig_scriptlets
|
|
||||||
|
|
||||||
%check
|
|
||||||
cd build
|
|
||||||
ctest -V
|
|
||||||
cd ..
|
|
||||||
%if %{with python2}
|
|
||||||
%{__python2} setup.py test
|
|
||||||
%endif
|
|
||||||
%{__python3} setup.py test
|
|
||||||
|
|
||||||
%files
|
|
||||||
%{_bindir}/brotli
|
|
||||||
%{_libdir}/*.so.*
|
|
||||||
%license LICENSE
|
|
||||||
|
|
||||||
# Note that there is no %%files section for the unversioned python module
|
|
||||||
# if we are building for several python runtimes
|
|
||||||
%if %{with python2}
|
|
||||||
%files -n python2-%{name}
|
|
||||||
%{python2_sitearch}/*
|
|
||||||
%license LICENSE
|
|
||||||
%endif
|
|
||||||
|
|
||||||
%files -n python3-%{name}
|
|
||||||
%{python3_sitearch}/*
|
|
||||||
%license LICENSE
|
|
||||||
|
|
||||||
%files -n %{name}-devel
|
|
||||||
%{_includedir}/*
|
|
||||||
%{_libdir}/*.so
|
|
||||||
%{_libdir}/pkgconfig/*
|
|
||||||
%{_mandir}/man3/*
|
|
||||||
|
|
||||||
|
|
||||||
%changelog
|
|
||||||
* Wed Jan 28 2026 Parag Nemade <pnemade AT redhat DOT com> - 1.0.6-4
|
|
||||||
- Resolves: RHEL-133986
|
|
||||||
CVE-2025-6176 Brotli decompression bomb DoS in scrapy
|
|
||||||
|
|
||||||
* Thu Oct 01 2020 Eike Rathke <erack@redhat.com> - 1.0.6-3
|
|
||||||
- Resolves: CVE-2020-8927
|
|
||||||
|
|
||||||
* Wed Jun 17 2020 Eike Rathke <erack@redhat.com> - 1.0.6-2
|
|
||||||
- Resolves: rhbz#1737412 bump NRV for build to compose
|
|
||||||
|
|
||||||
* Wed Oct 10 2018 Tomas Popela <tpopela@redhat.com> - 1.0.6-1
|
|
||||||
- Update to 1.0.6
|
|
||||||
- Resolves: rhbz#1637408
|
|
||||||
|
|
||||||
* Wed Sep 19 2018 Tomas Orsava <torsava@redhat.com> - 1.0.5-2
|
|
||||||
- Require the Python interpreter directly instead of using the package name
|
|
||||||
- Related: rhbz#1619153
|
|
||||||
|
|
||||||
* Mon Jul 16 2018 Tomas Popela <tpopela@redhat.com> - 1.0.5-1
|
|
||||||
- Update to 1.0.5
|
|
||||||
|
|
||||||
* Tue Jun 19 2018 Lumír Balhar <lbalhar@redhat.com> - 1.0.1-4
|
|
||||||
- Python 2 subpackage disabled
|
|
||||||
|
|
||||||
* Wed Feb 07 2018 Fedora Release Engineering <releng@fedoraproject.org> - 1.0.1-3
|
|
||||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild
|
|
||||||
|
|
||||||
* Sat Feb 03 2018 Igor Gnatenko <ignatenkobrain@fedoraproject.org> - 1.0.1-2
|
|
||||||
- Switch to %%ldconfig_scriptlets
|
|
||||||
|
|
||||||
* Fri Sep 22 2017 Travis Kendrick <pouar@pouar.net> - 1.0.1-1
|
|
||||||
- update to 1.0.1
|
|
||||||
|
|
||||||
* Wed Aug 02 2017 Fedora Release Engineering <releng@fedoraproject.org> - 0.6.0-6
|
|
||||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild
|
|
||||||
|
|
||||||
* Wed Jul 26 2017 Fedora Release Engineering <releng@fedoraproject.org> - 0.6.0-5
|
|
||||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild
|
|
||||||
|
|
||||||
* Tue May 23 2017 Travis Kendrick <pouar@pouar.net> - 0.6.0-4
|
|
||||||
- add man pages
|
|
||||||
|
|
||||||
* Sun May 14 2017 Travis Kendrick <pouar@pouar.net> - 0.6.0-3
|
|
||||||
- wrong directory for ctest
|
|
||||||
- LICENSE not needed in -devel
|
|
||||||
- fix "spurious-executable-perm"
|
|
||||||
- rpmbuild does the cleaning for us, so 'rm -rf %%{buildroot}' isn't needed
|
|
||||||
|
|
||||||
* Sat May 13 2017 Travis Kendrick <pouar@pouar.net> - 0.6.0-2
|
|
||||||
- include libraries and development files
|
|
||||||
|
|
||||||
* Sat May 06 2017 Travis Kendrick <pouar@pouar.net> - 0.6.0-1
|
|
||||||
- Initial build
|
|
||||||
307
brotli.spec
Normal file
307
brotli.spec
Normal file
@ -0,0 +1,307 @@
|
|||||||
|
Name: brotli
|
||||||
|
Version: 1.1.0
|
||||||
|
Release: 7%{?dist}
|
||||||
|
Summary: Lossless compression algorithm
|
||||||
|
|
||||||
|
License: MIT
|
||||||
|
URL: https://github.com/google/brotli
|
||||||
|
Source0: %{url}/archive/v%{version}/%{name}-%{version}.tar.gz
|
||||||
|
|
||||||
|
Patch1: RHEL-32153-kBrotliBitMask-bounds.patch
|
||||||
|
# Modified patch from upstream https://github.com/google/brotli/pull/1234/
|
||||||
|
# dropped binary part of updating test files from this patch
|
||||||
|
Patch2: CVE-2025-6176-brotli-1234.patch
|
||||||
|
|
||||||
|
%if 0%{?rhel} == 7
|
||||||
|
BuildRequires: devtoolset-7-toolchain, devtoolset-7-libatomic-devel
|
||||||
|
BuildRequires: cmake3
|
||||||
|
%else
|
||||||
|
BuildRequires: cmake
|
||||||
|
%endif
|
||||||
|
BuildRequires: gcc
|
||||||
|
BuildRequires: gcc-c++
|
||||||
|
BuildRequires: python%{python3_pkgversion}-devel
|
||||||
|
BuildRequires: python%{python3_pkgversion}-setuptools
|
||||||
|
Requires: lib%{name}%{?_isa} = %{version}-%{release}
|
||||||
|
|
||||||
|
%description
|
||||||
|
Brotli is a generic-purpose lossless compression algorithm that compresses
|
||||||
|
data using a combination of a modern variant of the LZ77 algorithm, Huffman
|
||||||
|
coding and 2nd order context modeling, with a compression ratio comparable
|
||||||
|
to the best currently available general-purpose compression methods.
|
||||||
|
It is similar in speed with deflate but offers more dense compression.
|
||||||
|
|
||||||
|
%package -n libbrotli
|
||||||
|
Summary: Library for brotli lossless compression algorithm
|
||||||
|
|
||||||
|
%description -n libbrotli
|
||||||
|
Brotli is a generic-purpose lossless compression algorithm that compresses
|
||||||
|
data using a combination of a modern variant of the LZ77 algorithm, Huffman
|
||||||
|
coding and 2nd order context modeling, with a compression ratio comparable
|
||||||
|
to the best currently available general-purpose compression methods.
|
||||||
|
It is similar in speed with deflate but offers more dense compression.
|
||||||
|
|
||||||
|
|
||||||
|
%package -n python%{python3_pkgversion}-%{name}
|
||||||
|
Summary: Lossless compression algorithm (python 3)
|
||||||
|
%{?python_provide:%python_provide python%{python3_pkgversion}-%{name}}
|
||||||
|
|
||||||
|
%description -n python%{python3_pkgversion}-%{name}
|
||||||
|
Brotli is a generic-purpose lossless compression algorithm that compresses
|
||||||
|
data using a combination of a modern variant of the LZ77 algorithm, Huffman
|
||||||
|
coding and 2nd order context modeling, with a compression ratio comparable
|
||||||
|
to the best currently available general-purpose compression methods.
|
||||||
|
It is similar in speed with deflate but offers more dense compression.
|
||||||
|
This package installs a Python 3 module.
|
||||||
|
|
||||||
|
|
||||||
|
%package devel
|
||||||
|
Summary: Lossless compression algorithm (development files)
|
||||||
|
Requires: %{name}%{?_isa} = %{version}-%{release}
|
||||||
|
Requires: lib%{name}%{?_isa} = %{version}-%{release}
|
||||||
|
|
||||||
|
%description devel
|
||||||
|
Brotli is a generic-purpose lossless compression algorithm that compresses
|
||||||
|
data using a combination of a modern variant of the LZ77 algorithm, Huffman
|
||||||
|
coding and 2nd order context modeling, with a compression ratio comparable
|
||||||
|
to the best currently available general-purpose compression methods.
|
||||||
|
It is similar in speed with deflate but offers more dense compression.
|
||||||
|
This package installs the development files
|
||||||
|
|
||||||
|
%prep
|
||||||
|
%autosetup -p1
|
||||||
|
# fix permissions for -debuginfo
|
||||||
|
# rpmlint will complain if I create an extra %%files section for
|
||||||
|
# -debuginfo for this so we'll put it here instead
|
||||||
|
chmod 644 c/enc/*.[ch]
|
||||||
|
chmod 644 c/include/brotli/*.h
|
||||||
|
chmod 644 c/tools/brotli.c
|
||||||
|
|
||||||
|
%build
|
||||||
|
%if 0%{?rhel} == 7
|
||||||
|
. /opt/rh/devtoolset-7/enable
|
||||||
|
%cmake3 \
|
||||||
|
-DCMAKE_INSTALL_PREFIX="%{_prefix}" \
|
||||||
|
-DCMAKE_INSTALL_LIBDIR="%{_libdir}"
|
||||||
|
%cmake3_build
|
||||||
|
%else
|
||||||
|
%cmake \
|
||||||
|
-DCMAKE_INSTALL_PREFIX="%{_prefix}" \
|
||||||
|
-DCMAKE_INSTALL_LIBDIR="%{_libdir}"
|
||||||
|
%cmake_build
|
||||||
|
%endif
|
||||||
|
%py3_build
|
||||||
|
|
||||||
|
%install
|
||||||
|
%if 0%{?rhel} == 7
|
||||||
|
. /opt/rh/devtoolset-7/enable
|
||||||
|
%cmake3_install
|
||||||
|
%else
|
||||||
|
%cmake_install
|
||||||
|
%endif
|
||||||
|
|
||||||
|
# I couldn't find the option to not build the static libraries
|
||||||
|
#rm "%{buildroot}%{_libdir}/"*.a
|
||||||
|
|
||||||
|
%py3_install
|
||||||
|
install -dm755 "%{buildroot}%{_mandir}/man3"
|
||||||
|
cd docs
|
||||||
|
for i in *.3;do
|
||||||
|
install -m644 "$i" "%{buildroot}%{_mandir}/man3/${i}brotli"
|
||||||
|
done
|
||||||
|
|
||||||
|
%ldconfig_scriptlets
|
||||||
|
|
||||||
|
%check
|
||||||
|
%if 0%{?rhel} == 7
|
||||||
|
. /opt/rh/devtoolset-7/enable
|
||||||
|
%ctest3
|
||||||
|
%else
|
||||||
|
%ctest
|
||||||
|
%endif
|
||||||
|
|
||||||
|
%files
|
||||||
|
%{_bindir}/brotli
|
||||||
|
|
||||||
|
%files -n libbrotli
|
||||||
|
%license LICENSE
|
||||||
|
%{_libdir}/libbrotlicommon.so.1*
|
||||||
|
%{_libdir}/libbrotlidec.so.1*
|
||||||
|
%{_libdir}/libbrotlienc.so.1*
|
||||||
|
|
||||||
|
# Note that there is no %%files section for the unversioned python module
|
||||||
|
# if we are building for several python runtimes
|
||||||
|
%files -n python%{python3_pkgversion}-%{name}
|
||||||
|
%license LICENSE
|
||||||
|
%{python3_sitearch}/brotli.py
|
||||||
|
%{python3_sitearch}/_brotli.cpython-%{python3_version_nodots}*.so
|
||||||
|
%{python3_sitearch}/__pycache__/brotli.cpython-%{python3_version_nodots}*.py*
|
||||||
|
%{python3_sitearch}/Brotli-1.1.0-py%{python3_version}.egg-info/
|
||||||
|
|
||||||
|
%files devel
|
||||||
|
%{_includedir}/brotli
|
||||||
|
%{_libdir}/libbrotlicommon.so
|
||||||
|
%{_libdir}/libbrotlidec.so
|
||||||
|
%{_libdir}/libbrotlienc.so
|
||||||
|
%{_libdir}/pkgconfig/libbrotlicommon.pc
|
||||||
|
%{_libdir}/pkgconfig/libbrotlidec.pc
|
||||||
|
%{_libdir}/pkgconfig/libbrotlienc.pc
|
||||||
|
%{_mandir}/man3/constants.h.3brotli*
|
||||||
|
%{_mandir}/man3/decode.h.3brotli*
|
||||||
|
%{_mandir}/man3/encode.h.3brotli*
|
||||||
|
%{_mandir}/man3/types.h.3brotli*
|
||||||
|
|
||||||
|
|
||||||
|
%changelog
|
||||||
|
* Thu Dec 18 2025 Parag Nemade <pnemade AT redhat DOT com> - 1.1.0-7
|
||||||
|
- Resolves: RHEL-133984
|
||||||
|
CVE-2025-6176 Brotli decompression bomb DoS in scrapy
|
||||||
|
|
||||||
|
* Tue Oct 29 2024 Troy Dawson <tdawson@redhat.com> - 1.1.0-6
|
||||||
|
- Bump release for October 2024 mass rebuild:
|
||||||
|
Resolves: RHEL-64018
|
||||||
|
|
||||||
|
* Wed Sep 11 2024 Eike Rathke <erack@redhat.com> - 1.1.0-5
|
||||||
|
- Check BitMask(n) n value for kBrotliBitMask[n] bounds
|
||||||
|
|
||||||
|
* Mon Jun 24 2024 Troy Dawson <tdawson@redhat.com> - 1.1.0-4
|
||||||
|
- Bump release for June 2024 mass rebuild
|
||||||
|
|
||||||
|
* Tue Jan 23 2024 Fedora Release Engineering <releng@fedoraproject.org> - 1.1.0-3
|
||||||
|
- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild
|
||||||
|
|
||||||
|
* Fri Jan 19 2024 Fedora Release Engineering <releng@fedoraproject.org> - 1.1.0-2
|
||||||
|
- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild
|
||||||
|
|
||||||
|
* Fri Sep 15 2023 Jonathan Wright <jonathan@almalinux.org> - 1.1.0-1
|
||||||
|
- Update to 1.1.1 rhbz#2233368
|
||||||
|
|
||||||
|
* Wed Jul 19 2023 Fedora Release Engineering <releng@fedoraproject.org> - 1.0.9-13
|
||||||
|
- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild
|
||||||
|
|
||||||
|
* Tue Jun 13 2023 Python Maint <python-maint@redhat.com> - 1.0.9-12
|
||||||
|
- Rebuilt for Python 3.12
|
||||||
|
|
||||||
|
* Wed Jan 18 2023 Fedora Release Engineering <releng@fedoraproject.org> - 1.0.9-11
|
||||||
|
- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild
|
||||||
|
|
||||||
|
* Sat Dec 03 2022 Jonathan Wright <jonathan@almalinux.org> - 1.0.9-10
|
||||||
|
- Fix EL7 builds
|
||||||
|
|
||||||
|
* Wed Jul 20 2022 Fedora Release Engineering <releng@fedoraproject.org> - 1.0.9-9
|
||||||
|
- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild
|
||||||
|
|
||||||
|
* Mon Jun 13 2022 Python Maint <python-maint@redhat.com> - 1.0.9-8
|
||||||
|
- Rebuilt for Python 3.11
|
||||||
|
|
||||||
|
* Wed Jan 19 2022 Fedora Release Engineering <releng@fedoraproject.org> - 1.0.9-7
|
||||||
|
- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild
|
||||||
|
|
||||||
|
* Wed Jul 21 2021 Fedora Release Engineering <releng@fedoraproject.org> - 1.0.9-6
|
||||||
|
- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild
|
||||||
|
|
||||||
|
* Thu Jun 03 2021 Python Maint <python-maint@redhat.com> - 1.0.9-5
|
||||||
|
- Rebuilt for Python 3.10
|
||||||
|
|
||||||
|
* Tue Jan 26 2021 Fedora Release Engineering <releng@fedoraproject.org> - 1.0.9-4
|
||||||
|
- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild
|
||||||
|
|
||||||
|
* Thu Oct 01 2020 Travis Kendrick <pouar@pouar.net> - 1.0.9-3
|
||||||
|
- Apparently %%autosetup calls %%patch on its own
|
||||||
|
|
||||||
|
* Thu Oct 01 2020 Travis Kendrick <pouar@pouar.net> - 1.0.9-2
|
||||||
|
- Fix pc file (#1884364)
|
||||||
|
|
||||||
|
* Wed Sep 30 2020 Travis Kendrick <pouar@pouar.net> - 1.0.9-1
|
||||||
|
- Update to 1.0.9 (#1872932)
|
||||||
|
|
||||||
|
* Wed Aug 12 2020 Carl George <carl@george.computer> - 1.0.7-14
|
||||||
|
- Update cmake invocation rhbz#1863298
|
||||||
|
|
||||||
|
* Sat Aug 01 2020 Fedora Release Engineering <releng@fedoraproject.org> - 1.0.7-13
|
||||||
|
- Second attempt - Rebuilt for
|
||||||
|
https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
|
||||||
|
|
||||||
|
* Mon Jul 27 2020 Fedora Release Engineering <releng@fedoraproject.org> - 1.0.7-12
|
||||||
|
- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
|
||||||
|
|
||||||
|
* Sat May 23 2020 Miro Hrončok <mhroncok@redhat.com> - 1.0.7-11
|
||||||
|
- Rebuilt for Python 3.9
|
||||||
|
|
||||||
|
* Tue Jan 28 2020 Fedora Release Engineering <releng@fedoraproject.org> - 1.0.7-10
|
||||||
|
- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
|
||||||
|
|
||||||
|
* Sat Dec 7 2019 Peter Robinson <pbrobinson@fedoraproject.org> 1.0.7-9
|
||||||
|
- Splil out the libs to a separate package
|
||||||
|
|
||||||
|
* Thu Oct 03 2019 Miro Hrončok <mhroncok@redhat.com> - 1.0.7-8
|
||||||
|
- Rebuilt for Python 3.8.0rc1 (#1748018)
|
||||||
|
|
||||||
|
* Sat Aug 17 2019 Miro Hrončok <mhroncok@redhat.com> - 1.0.7-7
|
||||||
|
- Rebuilt for Python 3.8
|
||||||
|
|
||||||
|
* Wed Jul 24 2019 Fedora Release Engineering <releng@fedoraproject.org> - 1.0.7-6
|
||||||
|
- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
|
||||||
|
|
||||||
|
* Sat Apr 20 2019 Orion Poplawski <orion@nwra.com> - 1.0.7-5
|
||||||
|
- Build with devtoolset-7 on EPEL7 to fix aarch64 builds
|
||||||
|
|
||||||
|
* Thu Mar 28 2019 Carl George <carl@george.computer> - 1.0.7-4
|
||||||
|
- EPEL compatibility
|
||||||
|
|
||||||
|
* Thu Jan 31 2019 Fedora Release Engineering <releng@fedoraproject.org> - 1.0.7-3
|
||||||
|
- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild
|
||||||
|
|
||||||
|
* Sun Dec 09 2018 Miro Hrončok <mhroncok@redhat.com> - 1.0.7-2
|
||||||
|
- Remove last python2 bits
|
||||||
|
|
||||||
|
* Wed Nov 28 2018 Travis Kendrick pouar@pouar.net> - 1.0.7-1
|
||||||
|
- Update to 1.0.7
|
||||||
|
|
||||||
|
* Wed Nov 28 2018 Travis Kendrick pouar@pouar.net> - 1.0.5-2
|
||||||
|
- remove Python 2 support https://fedoraproject.org/wiki/Changes/Mass_Python_2_Package_Removal
|
||||||
|
|
||||||
|
* Fri Jul 13 2018 Travis Kendrick pouar@pouar.net> - 1.0.5-1
|
||||||
|
- update to 1.0.5
|
||||||
|
|
||||||
|
* Thu Jul 12 2018 Fedora Release Engineering <releng@fedoraproject.org> - 1.0.4-4
|
||||||
|
- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild
|
||||||
|
|
||||||
|
* Mon Jun 18 2018 Miro Hrončok <mhroncok@redhat.com> - 1.0.4-3
|
||||||
|
- Rebuilt for Python 3.7
|
||||||
|
|
||||||
|
* Wed Apr 18 2018 Travis Kendrick pouar@pouar.net> - 1.0.4-2
|
||||||
|
- update to 1.0.4
|
||||||
|
|
||||||
|
* Sat Mar 03 2018 Travis Kendrick <pouar@pouar.net> - 1.0.3-1
|
||||||
|
- update to 1.0.3
|
||||||
|
|
||||||
|
* Wed Feb 07 2018 Fedora Release Engineering <releng@fedoraproject.org> - 1.0.1-3
|
||||||
|
- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild
|
||||||
|
|
||||||
|
* Sat Feb 03 2018 Igor Gnatenko <ignatenkobrain@fedoraproject.org> - 1.0.1-2
|
||||||
|
- Switch to %%ldconfig_scriptlets
|
||||||
|
|
||||||
|
* Fri Sep 22 2017 Travis Kendrick <pouar@pouar.net> - 1.0.1-1
|
||||||
|
- update to 1.0.1
|
||||||
|
|
||||||
|
* Wed Aug 02 2017 Fedora Release Engineering <releng@fedoraproject.org> - 0.6.0-6
|
||||||
|
- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild
|
||||||
|
|
||||||
|
* Wed Jul 26 2017 Fedora Release Engineering <releng@fedoraproject.org> - 0.6.0-5
|
||||||
|
- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild
|
||||||
|
|
||||||
|
* Tue May 23 2017 Travis Kendrick <pouar@pouar.net> - 0.6.0-4
|
||||||
|
- add man pages
|
||||||
|
|
||||||
|
* Sun May 14 2017 Travis Kendrick <pouar@pouar.net> - 0.6.0-3
|
||||||
|
- wrong directory for ctest
|
||||||
|
- LICENSE not needed in -devel
|
||||||
|
- fix "spurious-executable-perm"
|
||||||
|
- rpmbuild does the cleaning for us, so 'rm -rf %%{buildroot}' isn't needed
|
||||||
|
|
||||||
|
* Sat May 13 2017 Travis Kendrick <pouar@pouar.net> - 0.6.0-2
|
||||||
|
- include libraries and development files
|
||||||
|
|
||||||
|
* Sat May 06 2017 Travis Kendrick <pouar@pouar.net> - 0.6.0-1
|
||||||
|
- Initial build
|
||||||
Loading…
Reference in New Issue
Block a user