Smaz - short strings compression library
github.com
github.com
Don't run smaz() on untrusted input. Two things you need to fix, and a general word of advice:
(1) In the 0xFE case, you check for headroom in the output buffer but not the input buffer. If 0xFE is the last character in the input, you run right off the end of it, dumping the contents of memory to the output string.
(2) In the 0xFF case, same thing; if 0xFF 0xFE are the last characters in the buffer, I get at least 254 bytes of surrounding memory in my output.
How big a deal this is depends on what's in memory (and where the buffers are being kept). Generally, these are going to be on the stack, thus, a big deal.
General advice: not in love with using signed integers for byte counts; also, I don't think you have this problem because you're using full width integers, but be aware that your length bytes can theoretically wrap back to 0 if you're ever not careful in the future.
DON'T DATE ROBOTS.
Also note that the access is read only, so basically it's not possible to use such thing to run unprivileged code. Also in moder operating systems pages are zeroed before to be used in a different process, so it is not possible to read part of memory about a different process.
Thanks for the hint
In this case you'd be getting unsafe data for both compression and decompression.
I really like your project though. Thanks for sharing!
(1) It is extremely common for network apps to decompress blobs they didn't generate; even in cases where those blobs aren't passed client/server, but are instead roundtripped through a database or shared persistence layer.
(2) Whatever fastlz may do, the industry standard (in Win32 and Unix and in embedded devices) is zlib --- at least from what we've found on app pentests --- and zlib doesn't have this problem (now).
(3) Zlib is itself a minefield of vulnerabilities, which supports the point that your compression codec is a security hotspot for an application.
But my point isn't that your code sucks; it's nice and tight.
2) Right, but a define to don't this checks is useful for environments where data can be trusted but speed is very important.
3) Good point. I'll fix the code. Btw what is nice about that kind of things is that testing against random data helps a lot.
Zlib should do that. For example, do you remember the old security bug of old bind implementations of using a 'ptr' opcode (used for compression) in DNS packets in order to create an infinite loop and mount a DoS? Years ago I tested how this bug were trivial to spot just processing random data. This is true for a lot of applications.
If you know how the application works you can "tune" this random data with biases that will stimulate a lot more the code. This is a worthy testing tool that is underused IMHO.
Thanks for your comment.
David Molnar at Berkeley has done a ton of work on smart fuzzing: http://www.cs.berkeley.edu/~dmolnar/
Ilja van Sprundel wrote what has got to be the most popular "dumb" fuzzer, mangle.c: http://www.digitaldwarf.be/products/mangle.c
Mangle routinely finds horrible, horrible things in modern code; Ilja deserves some kind of anti-Nobel Prize for it.
It's code of few hours ago, but should be pretty stable already, with this kind of programming what's nice is that you can encrypt/decrypt millions of strings from /dev/urandom to spot obvious bugs in very short time.
I wonder if this lib can be useful to somebody else.
Some example:
'This is a small string' compressed by 50%
'foobar' compressed by 34%
'the end' compressed by 58%
'not-a-g00d-Exampl333' enlarged by 15%
'Smaz is a simple compression library' compressed by 39%
'Nothing is more difficult, and therefore more precious, than to be able to decide' compressed by 49%
'this is an example of what works very well with smaz' compressed by 49%
'1000 numbers 2000 will 10 20 30 compress very little' compressed by 10%immagine you want to store millions of SMS messages into a memcached or Redis server. Memory usage can be a problem, compressing this data with Smaz you can use half the number of servers needed otherwise. The same works for URLs as well. Compression examples against URLs:
'http://google.com' compressed by 59%
'http://programming.reddit.com' compressed by 52%
'http://github.com/antirez/smaz/tree/master' compressed by 46%How many of those pseudorandom strings are you able to compress, in general?
To stress more the compression with valid sequences it's possible to use a very big HTML file and get ranges at random instead to get this strings from /dev/urandom
It's basically a simple table-lookup, with two special bytes needed to emit verbatim bytes.
I think this can be an option that can be done in a second-pass way if a given #define is active. Thanks for the useful comment.
(1) compress better; and
(2) be more robust/self-documenting.
EG: "Feed this dictionary, optimized over 1 billion [English|Western language|etc] documents, to zlib deflateSetDictionary() before compressing."
(The zlib/gzip dictionary is only 32KiB, but the lzma dictionary can be up to 32MiB.)
Building a small library of standard dictionaries, keyed by hash (so they can be locally cached or fetched when needed) would offer good coverage of many string domains.
See for example the Google 'Shared Dictionary Compression over HTTP (SDCH)' proposal, apparently a feature of Google Toolbar:
http://sdch.googlegroups.com/web/Shared_Dictionary_Compressi...
I'm not exploiting an arithmetic encoding basically, and the dictionary is (intentionally) small. Add to this lib an arithmetic encoding and you get near to a zlib with an optimized dictionary, but at the cost of a lot of speed.