# # # patch "basic_io.hh" # from [6b126a5b42e3eba99b5aa01b73d3b2f7ffce5b1c] # to [08c95a11e0a8f44b196e47b7f6c6c1fe163a08c3] # # patch "cert.cc" # from [0bc1e3ef1f3815c8ec8aca3316d2438183fc6e3e] # to [cbb51430e3339065050062ae72c3ce93bdb44d76] # # patch "cert.hh" # from [03b1552a547510f0c4f20292011a87143ee9366f] # to [20e41af5acfac97a552e926e8dcae84de38e5f42] # # patch "database.cc" # from [d0da4979961345a3f6f4b68769910f3ba3943f81] # to [6cba21739e7949790b992932cca313d37799703e] # # patch "netio.hh" # from [269bd35395cac3a37446b365790f1fd505dbcd36] # to [68bc41e1df3d57e7a74eb5cf6249b68d29412f3d] # # patch "netsync.cc" # from [2389c7ac9c2468b5d2f974076204bf2640f1bde7] # to [bae7d1252b532383fd50bbdd0da5b842f65baa4c] # # patch "revision.cc" # from [77e9097ab359fa100476dd86924c6ab62d3387fc] # to [d90651ce5d000d0d595fa77e096417810dfd8c56] # # patch "revision.hh" # from [80779e60e01a93a50f50e5c2c3b8e291b6130831] # to [662d08e174ffe25cfc3840477fd94f873cbb4018] # # patch "sanity.hh" # from [67a009db0bbdd3565a7021f61e5b1e4a7194f480] # to [d42c4c449c5f9defedd339cb0e84230b690272c3] # # patch "transforms.hh" # from [095efe154a13776a48e780532833a79ad32b2297] # to [4f94047e0e3fb1446341d9dd0cbeb7c4a3fcd813] # # patch "vocab.cc" # from [164af638b42b1255dd2cffa88b56803c98a004fe] # to [bfd615381b80a2e37b845ecdc0376e79c7b18123] # # patch "vocab.hh" # from [795b362dc61a675f612d99608c8722d1735b2ff0] # to [8519acc2d76a0ae326f0935adcea296391d2d750] # # patch "vocab_macros.hh" # from [6fe5da4585e77ac009b38e567aec9a362194cc88] # to [d90361259f5e176d9076216b5e9effbdc48bff55] # ============================================================ --- basic_io.hh 6b126a5b42e3eba99b5aa01b73d3b2f7ffce5b1c +++ basic_io.hh 08c95a11e0a8f44b196e47b7f6c6c1fe163a08c3 @@ -61,7 +61,7 @@ namespace basic_io } token_type; struct - input_source + input_source : public origin_aware { size_t line, col; std::string const & in; ============================================================ --- cert.cc 0bc1e3ef1f3815c8ec8aca3316d2438183fc6e3e +++ cert.cc cbb51430e3339065050062ae72c3ce93bdb44d76 @@ -231,6 +231,11 @@ cert::cert(std::string const & s) { read_cert(s, *this); } +cert::cert(std::string const & s, made_from_t m) + : origin_aware(m) +{ + read_cert(s, *this); +} cert::cert(revision_id const & ident, cert_name const & name, ============================================================ --- cert.hh 03b1552a547510f0c4f20292011a87143ee9366f +++ cert.hh 20e41af5acfac97a552e926e8dcae84de38e5f42 @@ -28,12 +28,13 @@ struct options; class project_t; struct options; -struct cert +struct cert : public origin_aware { cert(); // This is to make revision and manifest work. explicit cert(std::string const & s); + cert(std::string const & s, made_from_t m); cert(revision_id const & ident, cert_name const & name, ============================================================ --- database.cc d0da4979961345a3f6f4b68769910f3ba3943f81 +++ database.cc 6cba21739e7949790b992932cca313d37799703e @@ -2514,6 +2514,7 @@ database::put_roster_for_revision(revisi MM(roster_manifest_id); make_roster_for_revision(*this, rev, new_id, *ros_writeable, *mm_writeable); calculate_ident(*ros_writeable, roster_manifest_id); + made_from_t made_from(rev.made_from); I(rev.new_manifest == roster_manifest_id); // const'ify the objects, suitable for caching etc. roster_t_cp ros = ros_writeable; ============================================================ --- netio.hh 269bd35395cac3a37446b365790f1fd505dbcd36 +++ netio.hh 68bc41e1df3d57e7a74eb5cf6249b68d29412f3d @@ -19,11 +19,6 @@ #include "sanity.hh" #include "string_queue.hh" -struct bad_decode { - bad_decode(i18n_format const & fmt) : what(fmt.str()) {} - std::string what; -}; - inline void require_bytes(std::string const & str, size_t pos, ============================================================ --- netsync.cc 2389c7ac9c2468b5d2f974076204bf2640f1bde7 +++ netsync.cc bae7d1252b532383fd50bbdd0da5b842f65baa4c @@ -2272,7 +2272,10 @@ session::process_data_cmd(netcmd_item_ty case revision_item: { L(FL("received revision '%s'") % hitem()); - if (project.db.put_revision(revision_id(item), revision_data(dat))) + revision_t rev; + rev.made_from = made_from_network; + read_revision(data(dat), rev); + if (project.db.put_revision(revision_id(item), rev)) written_revisions.push_back(revision_id(item)); } break; ============================================================ --- revision.cc 77e9097ab359fa100476dd86924c6ab62d3387fc +++ revision.cc d90651ce5d000d0d595fa77e096417810dfd8c56 @@ -119,6 +119,7 @@ revision_t::revision_t(revision_t const } revision_t::revision_t(revision_t const & other) + : origin_aware(other) { /* behave like normal constructor if other is empty */ made_for = made_for_nobody; @@ -1822,7 +1823,7 @@ parse_edge(basic_io::parser & parser, void parse_edge(basic_io::parser & parser, - edge_map & es) + revision_t & rev) { shared_ptr cs(new cset()); MM(*cs); @@ -1836,7 +1837,7 @@ parse_edge(basic_io::parser & parser, parse_cset(parser, *cs); - es.insert(make_pair(old_rev, cs)); + rev.edges.insert(make_pair(old_rev, cs)); } @@ -1857,9 +1858,9 @@ parse_revision(basic_io::parser & parser % tmp); parser.esym(syms::new_manifest); parser.hex(tmp); - rev.new_manifest = manifest_id(decode_hexenc(tmp)); + rev.new_manifest = manifest_id(decode_hexenc(tmp), made_from_network); while (parser.symp(syms::old_revision)) - parse_edge(parser, rev.edges); + parse_edge(parser, rev); rev.check_sane(); } @@ -1869,6 +1870,10 @@ read_revision(data const & dat, { MM(rev); basic_io::input_source src(dat(), "revision"); + // FIXME: maybe this is backwards, and made_from should + // come from @param{dat}? + src.made_from = rev.made_from; + made_from_t made_from(rev.made_from); basic_io::tokenizer tok(src); basic_io::parser pars(tok); parse_revision(pars, rev); @@ -1955,6 +1960,51 @@ UNIT_TEST(revision, find_old_new_path_fo I(foo_bar == find_new_path_for(renames, foo_baz)); } +UNIT_TEST(revision, from_network) +{ + char const * bad_revisions[] = { + "", + + "format_version \"1\"\n", + + "format_version \"1\"\n" + "\n" + "new_manifest [0000000000000000000000000000000000000000]\n", + + "format_version \"1\"\n" + "\n" + "new_manifest [000000000000000]\n", + + "format_version \"1\"\n" + "\n" + "new_manifest [0000000000000000000000000000000000000000]\n" + "\n" + "old_revision [66ff7f4640593afacdb056fefc069349e7d9ed9e]\n" + "\n" + "rename \"some_file\"\n" + " foo \"x\"\n", + + "format_version \"1\"\n" + "\n" + "new_manifest [0000000000000000000000000000000000000000]\n" + "\n" + "old_revision [66ff7f4640593afacdb056fefc069349e7d9ed9e]\n" + "\n" + "rename \"some_file\"\n" + " foo \"some_file\"\n" + }; + revision_t rev; + rev.made_from = made_from_network; + for (unsigned i = 0; i < sizeof(bad_revisions)/sizeof(char const*); ++i) + { + UNIT_TEST_CHECKPOINT((string("iteration ") + + boost::lexical_cast(i)).c_str()); + UNIT_TEST_CHECK_THROW(read_revision(data(bad_revisions[i]), + rev), + bad_decode); + } +} + #endif // BUILD_UNIT_TESTS // Local Variables: ============================================================ --- revision.hh 80779e60e01a93a50f50e5c2c3b8e291b6130831 +++ revision.hh 662d08e174ffe25cfc3840477fd94f873cbb4018 @@ -47,7 +47,7 @@ struct enum made_for { made_for_nobody, made_for_workspace, made_for_database }; struct -revision_t +revision_t : public origin_aware { void check_sane() const; bool is_merge_node() const; ============================================================ --- sanity.hh 67a009db0bbdd3565a7021f61e5b1e4a7194f480 +++ sanity.hh d42c4c449c5f9defedd339cb0e84230b690272c3 @@ -321,32 +321,70 @@ do { \ #define UNLIKELY(zz) (zz) #endif +struct bad_decode { + bad_decode(i18n_format const & fmt) : what(fmt.str()) {} + std::string what; +}; + +enum made_from_t { made_from_local, made_from_network }; +made_from_t const made_from = made_from_local; + +// Something that knows where it came from, so that its sanity checks +// can throw bad_decode instead of informative_error if it came from +// the network. +class origin_aware +{ +public: + made_from_t made_from; + origin_aware() : made_from(made_from_local) {} + origin_aware(made_from_t m) : made_from(m) {} +}; + // I is for invariants that "should" always be true // (if they are wrong, there is a *bug*) -#define I(e) \ -do { \ - if(UNLIKELY(!(e))) { \ - global_sanity.invariant_failure("I("#e")", __FILE__, __LINE__); \ - } \ -} while(0) +#define I(e) \ + do { \ + if (UNLIKELY(!(e))) \ + { \ + if (made_from == made_from_network) \ + throw bad_decode(F("%s:%s : %s") \ + % __FILE__ % __LINE__ % "I("#e")"); \ + else \ + global_sanity.invariant_failure("I("#e")", __FILE__, __LINE__); \ + } \ + } while (0) // N is for naughtyness on behalf of the user // (if they are wrong, the user just did something wrong) -#define N(e, explain)\ -do { \ - if(UNLIKELY(!(e))) { \ - global_sanity.naughty_failure("N("#e")", (explain), __FILE__, __LINE__); \ - } \ -} while(0) +#define N(e, explain) \ + do { \ + if (UNLIKELY(!(e))) \ + { \ + if (made_from == made_from_network) \ + throw bad_decode(F("%s:%s : %s") \ + % __FILE__ % __LINE__ % (explain)); \ + else \ + global_sanity.naughty_failure("N("#e")", \ + (explain), \ + __FILE__, __LINE__); \ + } \ + } while (0) // E is for errors; they are normal (i.e., not a bug), but not necessarily // attributable to user naughtiness -#define E(e, explain)\ -do { \ - if(UNLIKELY(!(e))) { \ - global_sanity.error_failure("E("#e")", (explain), __FILE__, __LINE__); \ - } \ -} while(0) +#define E(e, explain) \ + do { \ + if (UNLIKELY(!(e))) \ + { \ + if (made_from == made_from_network) \ + throw bad_decode(F("%s:%s : %s") \ + % __FILE__ % __LINE__ % (explain)); \ + else \ + global_sanity.error_failure("E("#e")", \ + (explain), \ + __FILE__, __LINE__); \ + } \ + } while (0) // Last gasp dumps ============================================================ --- transforms.hh 095efe154a13776a48e780532833a79ad32b2297 +++ transforms.hh 4f94047e0e3fb1446341d9dd0cbeb7c4a3fcd813 @@ -52,7 +52,7 @@ T decode_base64(base64 const & in) template T decode_base64(base64 const & in) -{ return T(xform(in())); } +{ return T(xform(in()), in.made_from); } template T decode_base64_as(std::string const & in) @@ -67,7 +67,7 @@ void decode_hexenc(hexenc const & in, template void decode_hexenc(hexenc const & in, T & out) -{ out = T(xform(in())); } +{ out = T(xform(in()), in.made_from); } inline std::string encode_hexenc(std::string const & in) { return xform(in); } @@ -83,7 +83,7 @@ void decode_gzip(gzip const & in, T & template void decode_gzip(gzip const & in, T & out) -{ out = T(xform(in())); } +{ out = T(xform(in()), in.made_from); } // string variant for netsync template ============================================================ --- vocab.cc 164af638b42b1255dd2cffa88b56803c98a004fe +++ vocab.cc bfd615381b80a2e37b845ecdc0376e79c7b18123 @@ -29,6 +29,7 @@ verify(hexenc const & val) inline void verify(hexenc const & val) { + made_from_t made_from(val.made_from); for (string::const_iterator i = val().begin(); i != val().end(); ++i) { N(is_xdigit(*i), @@ -43,6 +44,7 @@ verify(hexenc const & val) if (val().empty()) return; + made_from_t made_from(val.made_from); N(val().size() == constants::idlen, F("hex encoded ID '%s' size != %d") % val % constants::idlen); for (string::const_iterator i = val().begin(); i != val().end(); ++i) @@ -59,6 +61,7 @@ verify(id & val) if (val().empty()) return; + made_from_t made_from(val.made_from); N(val().size() == constants::idlen_bytes, F("invalid ID '%s'") % val); } @@ -66,6 +69,7 @@ verify(symbol const & val) inline void verify(symbol const & val) { + made_from_t made_from(val.made_from); for (string::const_iterator i = val().begin(); i != val().end(); ++i) { N(is_alnum(*i) || *i == '_', @@ -76,6 +80,7 @@ verify(cert_name const & val) inline void verify(cert_name const & val) { + made_from_t made_from(val.made_from); string::size_type pos = val().find_first_not_of(constants::legal_cert_name_bytes); N(pos == string::npos, F("bad character '%c' in cert name '%s'") % val().at(pos) % val); @@ -84,6 +89,7 @@ verify(rsa_keypair_id const & val) inline void verify(rsa_keypair_id const & val) { + made_from_t made_from(val.made_from); string::size_type pos = val().find_first_not_of(constants::legal_key_name_bytes); N(pos == string::npos, F("bad character '%c' in key name '%s'") % val().at(pos) % val); @@ -102,6 +108,7 @@ verify(netsync_session_key & val) return; } + made_from_t made_from(val.made_from); N(val().size() == constants::netsync_session_key_length_in_bytes, F("Invalid key length of %d bytes") % val().length()); } @@ -115,6 +122,7 @@ verify(netsync_hmac_value & val) return; } + made_from_t made_from(val.made_from); N(val().size() == constants::netsync_hmac_value_length_in_bytes, F("Invalid hmac length of %d bytes") % val().length()); } ============================================================ --- vocab.hh 795b362dc61a675f612d99608c8722d1735b2ff0 +++ vocab.hh 8519acc2d76a0ae326f0935adcea296391d2d750 @@ -12,6 +12,8 @@ #include +#include "sanity.hh" + // the purpose of this file is to wrap things which are otherwise strings // in a bit of typesafety, set up enumerations and tuple-types, and // generally describe the "vocabulary" (nouns anyways) that modules in this ============================================================ --- vocab_macros.hh 6fe5da4585e77ac009b38e567aec9a362194cc88 +++ vocab_macros.hh d90361259f5e176d9076216b5e9effbdc48bff55 @@ -14,11 +14,12 @@ template void dump(enc const &, std::string &); \ \ template \ -class enc { \ +class enc : public origin_aware { \ immutable_string s; \ public: \ enc() {} \ explicit enc(std::string const & s); \ + enc(std::string const & s, made_from_t m); \ enc(enc const & other); \ enc const & \ operator=(enc const & other); \ @@ -55,6 +56,7 @@ public: public: \ dec() {} \ explicit dec(std::string const & s); \ + dec(std::string const & s, made_from_t m); \ explicit dec(INNER const & inner); \ dec(dec const & other); \ bool operator<(dec const & x) const \ @@ -80,11 +82,12 @@ void dump(ty const &, std::string &); template <> \ void dump(ty const &, std::string &); \ \ -class ty { \ +class ty : public origin_aware { \ immutable_string s; \ public: \ ty() {} \ explicit ty(std::string const & str); \ + ty(std::string const & str, made_from_t m); \ ty(ty const & other); \ ty const & operator=(ty const & other); \ std::string const & operator()() const \ @@ -118,13 +121,23 @@ ty::ty(string const & str) : static size_t ty ## _tab_active = 0; \ \ ty::ty(string const & str) : \ + origin_aware(), \ s((ty ## _tab_active > 0) \ ? (ty ## _tab.unique(str)) \ : str) \ { verify(*this); } \ \ -ty::ty(ty const & other) : s(other.s) {} \ +ty::ty(string const & str, \ + made_from_t m) : \ + origin_aware(m), \ + s((ty ## _tab_active > 0) \ + ? (ty ## _tab.unique(str)) \ + : str) \ +{ verify(*this); } \ \ +ty::ty(ty const & other) : \ + origin_aware(other), s(other.s) {} \ + \ ty const & ty::operator=(ty const & other) \ { s = other.s; return *this; } \ \ @@ -141,6 +154,7 @@ ty::symtab::~symtab() \ ty::symtab::~symtab() \ { \ + made_from_t made_from(::made_from); \ I(ty ## _tab_active > 0); \ ty ## _tab_active--; \ if (ty ## _tab_active == 0) \ @@ -159,13 +173,23 @@ ty::ty(string const & str) : static size_t ty ## _tab_active = 0; \ \ ty::ty(string const & str) : \ + origin_aware(), \ s((ty ## _tab_active > 0) \ ? (ty ## _tab.unique(str)) \ : str) \ { verify(*this); } \ \ -ty::ty(ty const & other) : s(other.s) {} \ +ty::ty(string const & str, \ + made_from_t m) : \ + origin_aware(m), \ + s((ty ## _tab_active > 0) \ + ? (ty ## _tab.unique(str)) \ + : str) \ +{ verify(*this); } \ \ +ty::ty(ty const & other) : \ + origin_aware(other), s(other.s) {} \ + \ ty const & ty::operator=(ty const & other) \ { s = other.s; return *this; } \ \ @@ -178,6 +202,7 @@ ty::symtab::~symtab() \ ty::symtab::~symtab() \ { \ + made_from_t made_from(::made_from); \ I(ty ## _tab_active > 0); \ ty ## _tab_active--; \ if (ty ## _tab_active == 0) \ @@ -189,12 +214,18 @@ template #define cc_ENCODING(enc) \ \ template \ -enc::enc(string const & s) : s(s) \ +enc::enc(string const & s) : \ + origin_aware(), s(s) \ { verify(*this); } \ \ template \ +enc::enc(string const & s, made_from_t m) : \ + origin_aware(m), s(s) \ + { verify(*this); } \ + \ +template \ enc::enc(enc const & other) \ - : s(other.s) {} \ + : origin_aware(other), s(other.s) {} \ \ template \ enc const & \ @@ -228,6 +259,11 @@ template : i(s) { verify(i); } \ \ template \ +dec::dec(std::string const & s, \ + made_from_t m) \ + : i(s, m) { verify(i); } \ + \ +template \ dec::dec(INNER const & inner) \ : i(inner) {} \ \