# # # patch "ChangeLog" # from [1d874fef55c9d221bc0314fd736292ee06b048be] # to [6bfb3d4486d068407341d8d49e9b87cbc06c7c74] # # patch "botan/gzip.cpp" # from [c563ec78bac13eead84737e3047cb4f7027a77f0] # to [6e190f22df99d08404da49a1a52ef2d1f71a15da] # # patch "transforms.cc" # from [6fe2c600c4a2dacedb29497b3292a3e8c3728171] # to [3d76cc7d7a564fb292d5b579b1a2c9554572a595] # ============================================================ --- ChangeLog 1d874fef55c9d221bc0314fd736292ee06b048be +++ ChangeLog 6bfb3d4486d068407341d8d49e9b87cbc06c7c74 @@ -1,10 +1,20 @@ +2007-01-04 Zack Weinberg + + * botan/gzip.cpp: Use specific subclasses of Botan::Exception + throughout. + * transforms.cc (error_in_transform): New function. + (xform, pack, calculate_ident): Wrap use of Botan in try/catch, + and call error_in_transform if we catch a Botan exception. + (canonical_base64): Use Botan directly; add similar try/catch clause. + (corruption_check): New unit test. + 2007-01-03 Thomas Keller * work.cc: classify_roster_paths: if the inodeprints cache is enabled, unchanged and missing files are now handled properly for use in automate inventory (before any unchanged file was wrongly determined as missing) - + 2007-01-02 Thomas Moschny * std_hooks.lua (get_netsync_connect_command): Fix a typo. @@ -49,18 +59,18 @@ 2006-12-28 Derek Scherger * tests/missing_empty_dir/__driver__.lua: new test for missing, - empty, versioned directories + empty, versioned directories * testsuite.lua: call it * work.cc (update_current_roster_from_filesystem): abort if there are missing directories, whether they contained files or not. tweak the associated messages so they're a bit more specific about missing things verses things that are not what they should be, like files that should be directories and vice-versa. - + 2006-12-27 Richard Levitte * NEWS: Date the release. @@ -155,14 +165,14 @@ 2006-12-21 Thomas Keller * NEWS: refined some sections and added notes about - fixes in automate inventory and the localization code + fixes in automate inventory and the localization code 2006-12-19 Thomas Keller @@ -243,11 +253,11 @@ 2006-12-14 Thomas Keller - * work.cc: handle missing directories properly in - classify_roster_paths - * automate.cc: trailing slash also for missing directories - * tests/...: adapted automate_inventory test which now tests - for unknown, added (but missing) and dropped (uncommitted) dirs + * work.cc: handle missing directories properly in + classify_roster_paths + * automate.cc: trailing slash also for missing directories + * tests/...: adapted automate_inventory test which now tests + for unknown, added (but missing) and dropped (uncommitted) dirs 2006-12-14 Thomas Keller @@ -271,26 +281,26 @@ 2006-12-12 Ben Walton - - * cmd_ws_cc: Added mtn mkdir - * testsuite.lua: added mtn mkdir test - * included tests/mkdir as unit testing for mtn mkdir - * added documentation to monotone.texi + * cmd_ws_cc: Added mtn mkdir + * testsuite.lua: added mtn mkdir test + * included tests/mkdir as unit testing for mtn mkdir + * added documentation to monotone.texi + 2006-12-12 Thomas Moschny * HACKING: Updated "Patch submission guidelines" section. 2006-12-11 Ben Walton - - * cmd_ws_commit.cc, - tests/commit_using__MTN_log/commit_log_modified_return.lua, - tests/commit_using__MTN_log/__driver__.lua: - Added the requirement that when _MTN/log is pre-specified by - the user, that the user remove a 'magic' line prior to the - commit being accepted. Modified the units tests to verify this. - Updated texinfo to match this new behaviour. + * cmd_ws_commit.cc, + tests/commit_using__MTN_log/commit_log_modified_return.lua, + tests/commit_using__MTN_log/__driver__.lua: + Added the requirement that when _MTN/log is pre-specified by + the user, that the user remove a 'magic' line prior to the + commit being accepted. Modified the units tests to verify this. + Updated texinfo to match this new behaviour. + 2006-12-10 Timothy Brownawell Implement a "mtn log --to ", that doesn't log the @@ -442,7 +452,7 @@ 2006-11-20 Thomas Keller @@ -487,7 +497,7 @@ 2006-11-17 Thomas Keller - * cmd_automate.cc, cmd.hh, ...: renamed member variable + * cmd_automate.cc, cmd.hh, ...: renamed member variable "options" to "opts" to make (hopefully) the gcc-3.3 build slaves happy @@ -550,7 +560,7 @@ 2006-11-11 Thomas Moschny * notes/: New directory for developer docs. @@ -580,7 +590,7 @@ 2006-11-10 Nathaniel Smith Improved error message for invalid uri's (per bug #17736) @@ -745,7 +755,7 @@ 2006-10-03 Evan Deaubl * po/sv.po: 35 fuzzies cleared, @@ -850,7 +860,7 @@ 2006-09-23 Grahame Bowland - * automate.cc (get_content_changed): use the file_content + * automate.cc (get_content_changed): use the file_content make rather than the parent_name mark. 2006-09-23 Nathaniel Smith @@ -868,7 +878,7 @@ 2006-09-22 Nathaniel Smith * graph.cc: I dunno, maybe this will make the buildslaves happier? - + 2006-09-22 Nathaniel Smith * graph.cc: Add randomized tests for get_reconstruction_path. @@ -1599,7 +1609,7 @@ 2006-09-02 Matt Johnston - + * botan/: import of Botan 1.5 2006-08-31 Nathaniel Smith ============================================================ --- botan/gzip.cpp c563ec78bac13eead84737e3047cb4f7027a77f0 +++ botan/gzip.cpp 6e190f22df99d08404da49a1a52ef2d1f71a15da @@ -102,7 +102,7 @@ Gzip_Compression::Gzip_Compression(u32bi if(deflateInit2(&(zlib->stream), level, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY) != Z_OK) { delete zlib; zlib = 0; - throw Exception("Gzip_Compression: Memory allocation error"); + throw Memory_Exhaustion(); } } @@ -144,7 +144,7 @@ void Gzip_Compression::write(const byte zlib->stream.avail_out = buffer.size(); int rc = deflate(&(zlib->stream), Z_NO_FLUSH); if (rc != Z_OK && rc != Z_STREAM_END) - throw Exception("Internal error in Gzip_Compression deflate."); + throw Internal_Error("Gzip_Compression: deflate failed."); send(buffer.begin(), buffer.size() - zlib->stream.avail_out); } } @@ -164,7 +164,7 @@ void Gzip_Compression::end_msg() zlib->stream.avail_out = buffer.size(); rc = deflate(&(zlib->stream), Z_FINISH); if (rc != Z_OK && rc != Z_STREAM_END) - throw Exception("Internal error in Gzip_Compression finishing deflate."); + throw Internal_Error("Gzip_Compression: finishing deflate failed."); send(buffer.begin(), buffer.size() - zlib->stream.avail_out); } @@ -220,7 +220,7 @@ Gzip_Decompression::Gzip_Decompression() no_writes(true), pipe(new Hash_Filter("CRC32")), footer(0) { if (DEFAULT_BUFFERSIZE < sizeof(GZIP::GZIP_HEADER)) - throw Exception("DEFAULT_BUFFERSIZE is too small"); + throw Invalid_Argument("DEFAULT_BUFFERSIZE is too small"); zlib = new Zlib_Stream; @@ -229,7 +229,7 @@ Gzip_Decompression::Gzip_Decompression() if(inflateInit2(&(zlib->stream), -15) != Z_OK) { delete zlib; zlib = 0; - throw Exception("Gzip_Decompression: Memory allocation error"); + throw Memory_Exhaustion(); } } @@ -248,7 +248,7 @@ void Gzip_Decompression::start_msg() void Gzip_Decompression::start_msg() { if (!no_writes) - throw Exception("Gzip_Decompression: start_msg after already writing"); + throw Invalid_State("Gzip_Decompression: start_msg after already writing"); pipe.start_msg(); datacount = 0; @@ -309,8 +309,8 @@ void Gzip_Decompression::write(const byt if(rc == Z_NEED_DICT) throw Decoding_Error("Gzip_Decompression: Need preset dictionary"); if(rc == Z_MEM_ERROR) - throw Exception("Gzip_Decompression: Memory allocation error"); - throw Exception("Gzip_Decompression: Unknown decompress error"); + throw Memory_Exhaustion(); + throw Internal_Error("Gzip_Decompression: Unknown decompress error"); } send(buffer.begin(), buffer.size() - zlib->stream.avail_out); pipe.write(buffer.begin(), buffer.size() - zlib->stream.avail_out); @@ -356,7 +356,7 @@ void Gzip_Decompression::check_footer() void Gzip_Decompression::check_footer() { if (footer.size() != GZIP::FOOTER_LENGTH) - throw Exception("Gzip_Decompression: Error finalizing decompression"); + throw Decoding_Error("Gzip_Decompression: footer wrong length"); pipe.end_msg(); @@ -371,13 +371,13 @@ void Gzip_Decompression::check_footer() tmpbuf.set(footer.begin(), 4); if (buf != tmpbuf) - throw Exception("Gzip_Decompression: Data integrity error - CRC32 error"); + throw Decoding_Error("Gzip_Decompression: Data integrity error - CRC32 error"); // Check the length matches - it is encoded LSB-first for (int i = 0; i < 4; i++) { if (footer.begin()[GZIP::FOOTER_LENGTH-1-i] != get_byte(i, datacount)) - throw Exception("Gzip_Decompression: Data integrity error - incorrect length"); + throw Decoding_Error("Gzip_Decompression: Data integrity error - incorrect length"); } } @@ -392,7 +392,7 @@ void Gzip_Decompression::end_msg() // read, clear() will reset no_writes if(no_writes) return; - throw Exception("Gzip_Decompression: didn't find footer"); + throw Decoding_Error("Gzip_Decompression: didn't find footer"); } ============================================================ --- transforms.cc 6fe2c600c4a2dacedb29497b3292a3e8c3728171 +++ transforms.cc 3d76cc7d7a564fb292d5b579b1a2c9554572a595 @@ -14,8 +14,8 @@ #include #include #include -#include + #include #include @@ -60,13 +60,61 @@ using boost::scoped_array; // paradigm "must" be used. this program is intended for source code // control and I make no bones about it. +static void NORETURN +error_in_transform(Botan::Exception & e) +{ + // why do people make up their own out-of-memory exceptions? + if (typeid(e) == typeid(Botan::Memory_Exhaustion)) + throw std::bad_alloc(); + + // these classes can all indicate data corruption + else if (typeid(e) == typeid(Botan::Encoding_Error) + || typeid(e) == typeid(Botan::Decoding_Error) + || typeid(e) == typeid(Botan::Stream_IO_Error) + || typeid(e) == typeid(Botan::Integrity_Failure)) + { + // clean up the what() string a little: throw away the + // "botan: TYPE: " part... + string w(e.what()); + string::size_type pos = w.find(':'); + pos = w.find(':', pos+1); + w = string(w.begin() + pos + 2, w.end()); + + // ... downcase the rest of it and replace underscores with spaces. + for (string::iterator p = w.begin(); p != w.end(); p++) + if (::isupper(*p)) + *p = ::tolower(*p); + else if (*p == '_') + *p = ' '; + + E(false, + F("%s\n" + "this may be due to a memory glitch, data corruption during\n" + "a network transfer, corruption of your database or workspace,\n" + "or a bug in monotone. if the error persists, please contact\n" + "%s for assistance.\n") + % w % PACKAGE_BUGREPORT); + } + else + throw; + + I(false); // can't get here +} + // the generic function template string xform(string const & in) { string out; - Botan::Pipe pipe(new XFM()); - pipe.process_msg(in); - out = pipe.read_all_as_string(); + try + { + Botan::Pipe pipe(new XFM()); + pipe.process_msg(in); + out = pipe.read_all_as_string(); + } + catch (Botan::Exception & e) + { + error_in_transform(e); + } return out; } @@ -160,10 +208,18 @@ void pack(T const & in, base64< gzip string tmp; tmp.reserve(in().size()); // FIXME: do some benchmarking and make this a constant:: - Botan::Pipe pipe(new Botan::Gzip_Compression(), new Botan::Base64_Encoder); - pipe.process_msg(in()); - tmp = pipe.read_all_as_string(); - out = tmp; + try + { + Botan::Pipe pipe(new Botan::Gzip_Compression(), + new Botan::Base64_Encoder); + pipe.process_msg(in()); + tmp = pipe.read_all_as_string(); + out = tmp; + } + catch (Botan::Exception & e) + { + error_in_transform(e); + } } template @@ -172,11 +228,18 @@ void unpack(base64< gzip > const & in string tmp; tmp.reserve(in().size()); // FIXME: do some benchmarking and make this a constant:: - Botan::Pipe pipe(new Botan::Base64_Decoder(), new Botan::Gzip_Decompression()); - pipe.process_msg(in()); - tmp = pipe.read_all_as_string(); - - out = tmp; + try + { + Botan::Pipe pipe(new Botan::Base64_Decoder(), + new Botan::Gzip_Decompression()); + pipe.process_msg(in()); + tmp = pipe.read_all_as_string(); + out = tmp; + } + catch (Botan::Exception & e) + { + error_in_transform(e); + } } // specialise them @@ -213,10 +276,19 @@ calculate_ident(data const & dat, calculate_ident(data const & dat, hexenc & ident) { - Botan::Pipe p(new Botan::Hash_Filter("SHA-160")); - p.process_msg(dat()); - - id ident_decoded(p.read_all_as_string()); + string s; + try + { + Botan::Pipe p(new Botan::Hash_Filter("SHA-160")); + p.process_msg(dat()); + s = p.read_all_as_string(); + } + catch (Botan::Exception & e) + { + error_in_transform(e); + } + + id ident_decoded(s); encode_hexenc(ident_decoded, ident); } @@ -261,8 +333,17 @@ canonical_base64(string const & s) string canonical_base64(string const & s) { - return xform - (xform(s)); + try + { + Botan::Pipe pipe(new Botan::Base64_Decoder(), + new Botan::Base64_Encoder()); + pipe.process_msg(s); + return pipe.read_all_as_string(); + } + catch (Botan::Exception & e) + { + error_in_transform(e); + } } @@ -304,6 +385,24 @@ UNIT_TEST(transform, calculate_ident) BOOST_CHECK(output() == ident); } +UNIT_TEST(transform, corruption_check) +{ + data input(string("i'm so fragile, fragile when you're here")); + gzip gzd; + encode_gzip(input, gzd); + + // fake a single-bit error + string gzs = gzd(); + string::iterator i = gzs.begin(); + while (*i != '+') + i++; + *i = 'k'; + + gzip gzbad(gzs); + data output; + BOOST_CHECK_THROW(decode_gzip(gzbad, output), informative_failure); +} + #endif // BUILD_UNIT_TESTS // Local Variables: