byteorder = "~1.4.2"
uuid = "~0.8.2"
crc = "~1.8.1"
+lzma-rs = { version = "~0.2.0", features = ["stream"] }
memchr = "~2.4.1"
num = "~0.2.1"
num-derive = "~0.2.5"
pub mod quic;
pub mod bittorrent_dht;
pub mod plugin;
+pub mod lzma;
pub mod util;
pub mod ffi;
--- /dev/null
+/* Copyright (C) 2022 Open Information Security Foundation
+ *
+ * You can copy, redistribute or modify this Program under the terms of
+ * the GNU General Public License version 2 as published by the Free
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+use lzma_rs::decompress::{Options, Stream};
+use lzma_rs::error::Error;
+use std::io::{Cursor, Write};
+
+/// Propagate lzma crate errors
+#[repr(C)]
+pub enum LzmaStatus {
+ LzmaOk,
+ LzmaIoError,
+ LzmaHeaderTooShortError,
+ LzmaError,
+ LzmaMemoryError,
+ LzmaXzError,
+}
+
+impl From<Error> for LzmaStatus {
+ fn from(e: Error) -> LzmaStatus {
+ match e {
+ Error::IoError(_) => LzmaStatus::LzmaIoError,
+ Error::HeaderTooShort(_) => LzmaStatus::LzmaHeaderTooShortError,
+ Error::LzmaError(e) => {
+ if e.to_string().contains("exceeded memory limit") {
+ LzmaStatus::LzmaMemoryError
+ } else {
+ LzmaStatus::LzmaError
+ }
+ }
+ Error::XzError(_) => LzmaStatus::LzmaXzError,
+ }
+ }
+}
+
+impl From<std::io::Error> for LzmaStatus {
+ fn from(_e: std::io::Error) -> LzmaStatus {
+ LzmaStatus::LzmaIoError
+ }
+}
+
+/// Use the lzma algorithm to decompress a chunk of data.
+#[no_mangle]
+pub unsafe extern "C" fn lzma_decompress(
+ input: *const u8, input_len: &mut usize, output: *mut u8, output_len: &mut usize,
+ memlimit: usize,
+) -> LzmaStatus {
+ let input = std::slice::from_raw_parts(input, *input_len);
+ let output = std::slice::from_raw_parts_mut(output, *output_len);
+ let output = Cursor::new(output);
+
+ let options = Options {
+ memlimit: Some(memlimit),
+ allow_incomplete: true,
+ ..Default::default()
+ };
+
+ let mut stream = Stream::new_with_options(&options, output);
+
+ if let Err(e) = stream.write_all(input) {
+ return e.into();
+ }
+
+ match stream.finish() {
+ Ok(output) => {
+ *output_len = output.position() as usize;
+ LzmaStatus::LzmaOk
+ }
+ Err(e) => e.into(),
+ }
+}
{ "Z_STREAM_ERROR", FILE_DECODER_EVENT_Z_STREAM_ERROR },
{ "Z_BUF_ERROR", FILE_DECODER_EVENT_Z_BUF_ERROR },
{ "Z_UNKNOWN_ERROR", FILE_DECODER_EVENT_Z_UNKNOWN_ERROR },
+ { "LZMA_IO_ERROR", FILE_DECODER_EVENT_LZMA_IO_ERROR },
+ { "LZMA_HEADER_TOO_SHORT_ERROR", FILE_DECODER_EVENT_LZMA_HEADER_TOO_SHORT_ERROR },
{ "LZMA_DECODER_ERROR", FILE_DECODER_EVENT_LZMA_DECODER_ERROR },
{ "LZMA_MEMLIMIT_ERROR", FILE_DECODER_EVENT_LZMA_MEMLIMIT_ERROR },
- { "LZMA_OPTIONS_ERROR", FILE_DECODER_EVENT_LZMA_OPTIONS_ERROR },
- { "LZMA_FORMAT_ERROR", FILE_DECODER_EVENT_LZMA_FORMAT_ERROR },
- { "LZMA_DATA_ERROR", FILE_DECODER_EVENT_LZMA_DATA_ERROR },
- { "LZMA_BUF_ERROR", FILE_DECODER_EVENT_LZMA_BUF_ERROR },
+ { "LZMA_XZ_ERROR", FILE_DECODER_EVENT_LZMA_XZ_ERROR },
{ "LZMA_UNKNOWN_ERROR", FILE_DECODER_EVENT_LZMA_UNKNOWN_ERROR },
{
"TOO_MANY_BUFFERS",
FILE_DECODER_EVENT_Z_STREAM_ERROR,
FILE_DECODER_EVENT_Z_BUF_ERROR,
FILE_DECODER_EVENT_Z_UNKNOWN_ERROR,
+ FILE_DECODER_EVENT_LZMA_IO_ERROR,
+ FILE_DECODER_EVENT_LZMA_HEADER_TOO_SHORT_ERROR,
FILE_DECODER_EVENT_LZMA_DECODER_ERROR,
FILE_DECODER_EVENT_LZMA_MEMLIMIT_ERROR,
- FILE_DECODER_EVENT_LZMA_OPTIONS_ERROR,
- FILE_DECODER_EVENT_LZMA_FORMAT_ERROR,
- FILE_DECODER_EVENT_LZMA_DATA_ERROR,
- FILE_DECODER_EVENT_LZMA_BUF_ERROR,
+ FILE_DECODER_EVENT_LZMA_XZ_ERROR,
FILE_DECODER_EVENT_LZMA_UNKNOWN_ERROR,
DETECT_EVENT_TOO_MANY_BUFFERS,
#include "util-file-swf-decompression.h"
#include "util-misc.h"
#include "util-print.h"
+#include "util-validate.h"
-#include <zlib.h>
+#include "rust.h"
-#include <htp/lzma/LzmaDec.h>
+#include <zlib.h>
#define MAX_SWF_DECOMPRESSED_LEN 50000000
/*
return ret;
}
-static void *SzAlloc(ISzAllocPtr p, size_t size) { return malloc(size); }
-static void SzFree(ISzAllocPtr p, void *address) { free(address); }
-static const ISzAlloc suri_lzma_Alloc = { SzAlloc, SzFree };
-
/* ZWS format */
/*
* | 4 bytes | 4 bytes | 4 bytes | 5 bytes | n bytes | 6 bytes |
{
int ret = 0;
- CLzmaDec strm;
- LzmaDec_Construct(&strm);
- ELzmaStatus status;
-
- if (compressed_data_len < LZMA_PROPS_SIZE + 8) {
- DetectEngineSetEvent(det_ctx, FILE_DECODER_EVENT_LZMA_FORMAT_ERROR);
- return 0;
- }
- ret = LzmaDec_Allocate(&strm, compressed_data, LZMA_PROPS_SIZE, &suri_lzma_Alloc);
- if (ret != SZ_OK) {
- DetectEngineSetEvent(det_ctx, FILE_DECODER_EVENT_LZMA_DECODER_ERROR);
- return 0;
- }
- LzmaDec_Init(&strm);
- compressed_data += LZMA_PROPS_SIZE + 8;
- compressed_data_len -= LZMA_PROPS_SIZE + 8;
size_t inprocessed = compressed_data_len;
size_t outprocessed = decompressed_data_len;
- ret = LzmaDec_DecodeToBuf(&strm, decompressed_data, &outprocessed,
- compressed_data, &inprocessed, LZMA_FINISH_ANY, &status, MAX_SWF_DECOMPRESSED_LEN);
+ ret = lzma_decompress(compressed_data, &inprocessed, decompressed_data, &outprocessed,
+ MAX_SWF_DECOMPRESSED_LEN);
switch(ret) {
- case SZ_OK:
+ case LzmaOk:
ret = 1;
break;
- case SZ_ERROR_MEM:
- DetectEngineSetEvent(det_ctx, FILE_DECODER_EVENT_LZMA_MEMLIMIT_ERROR);
+ case LzmaIoError:
+ DetectEngineSetEvent(det_ctx, FILE_DECODER_EVENT_LZMA_IO_ERROR);
ret = 0;
break;
- case SZ_ERROR_UNSUPPORTED:
- DetectEngineSetEvent(det_ctx, FILE_DECODER_EVENT_LZMA_OPTIONS_ERROR);
+ case LzmaHeaderTooShortError:
+ DetectEngineSetEvent(det_ctx, FILE_DECODER_EVENT_LZMA_HEADER_TOO_SHORT_ERROR);
ret = 0;
break;
- case SZ_ERROR_DATA:
- DetectEngineSetEvent(det_ctx, FILE_DECODER_EVENT_LZMA_DATA_ERROR);
+ case LzmaError:
+ DetectEngineSetEvent(det_ctx, FILE_DECODER_EVENT_LZMA_DECODER_ERROR);
+ ret = 0;
+ break;
+ case LzmaMemoryError:
+ DetectEngineSetEvent(det_ctx, FILE_DECODER_EVENT_LZMA_MEMLIMIT_ERROR);
ret = 0;
break;
- case SZ_ERROR_INPUT_EOF:
- DetectEngineSetEvent(det_ctx, FILE_DECODER_EVENT_LZMA_BUF_ERROR);
+ case LzmaXzError:
+ /* We should not see XZ compressed SWF files */
+ DEBUG_VALIDATE_BUG_ON(ret == LzmaXzError);
+ DetectEngineSetEvent(det_ctx, FILE_DECODER_EVENT_LZMA_XZ_ERROR);
ret = 0;
break;
default:
break;
}
- LzmaDec_Free(&strm, &suri_lzma_Alloc);
return ret;
}