From 76764cf978d3fe0b37df368c821784982fd387b4 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Tue, 12 Jan 2021 11:09:07 -0800 Subject: [PATCH] xcode: capture file:line of fault() --- src/client.cpp | 12 ++++++------ src/clientconn.cpp | 2 +- src/clientget.cpp | 4 ++-- src/clientmon.cpp | 4 ++-- src/dataencode.cpp | 24 +++++++++++------------ src/evhelper.cpp | 4 ++-- src/pvaproto.h | 44 +++++++++++++++++++++++++------------------ src/server.cpp | 4 ++-- src/serverchan.cpp | 4 ++-- src/serverconn.cpp | 4 ++-- src/udp_collector.cpp | 12 ++++++------ test/testudp.cpp | 4 ++-- 12 files changed, 65 insertions(+), 57 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index 4836689..7118ddf 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -504,7 +504,7 @@ bool Context::Pvt::onSearch() FixedBuf M(be, searchMsg.data(), nrx); const uint8_t cmd = M[3]; - M.skip(4); + M.skip(4, __FILE__, __LINE__); uint32_t len=0; from_wire(M, len); @@ -524,7 +524,7 @@ bool Context::Pvt::onSearch() _from_wire<12>(M, &guid[0], false); // searchSequenceID // we don't use this and instead rely on ID for individual PVs - M.skip(4u); + M.skip(4u, __FILE__, __LINE__); from_wire(M, serv); if(serv.isAny()) @@ -534,7 +534,7 @@ bool Context::Pvt::onSearch() if(M.size()<4u || M[0]!=3u || M[1]!='t' || M[2]!='c' || M[3]!='p') return true; - M.skip(4u); + M.skip(4u, __FILE__, __LINE__); from_wire(M, found); if(!found) @@ -587,7 +587,7 @@ bool Context::Pvt::onSearch() } } else { - M.fault(); + M.fault(__FILE__, __LINE__); } if(!M.good()) { @@ -630,7 +630,7 @@ void Context::Pvt::tickSearch() while(!bucket.empty()) { searchMsg.resize(0x10000); FixedBuf M(true, searchMsg.data(), searchMsg.size()); - M.skip(8); // fill in header after body length known + M.skip(8, __FILE__, __LINE__); // fill in header after body length known // searchSequenceID // we don't use this and instead rely on IDs for individual PVs @@ -655,7 +655,7 @@ void Context::Pvt::tickSearch() // placeholder for channel count; auto pcount = M.save(); uint16_t count = 0u; - M.skip(2u); + M.skip(2u, __FILE__, __LINE__); bool payload = false; while(!bucket.empty()) { diff --git a/src/clientconn.cpp b/src/clientconn.cpp index 75dc0b6..3372d13 100644 --- a/src/clientconn.cpp +++ b/src/clientconn.cpp @@ -170,7 +170,7 @@ void Connection::handle_CONNECTION_VALIDATION() // unused // serverReceiveBufferSize // serverIntrospectionRegistryMaxSize - M.skip(4u + 2u); + M.skip(4u + 2u, __FILE__, __LINE__); Size nauth{}; from_wire(M, nauth); diff --git a/src/clientget.cpp b/src/clientget.cpp index 14b3587..883866c 100644 --- a/src/clientget.cpp +++ b/src/clientget.cpp @@ -334,7 +334,7 @@ void Connection::handle_GPR(pva_app_msg_t cmd) if(uint8_t(op->op)!=cmd) { // peer mixes up IOID and operation type - M.fault(); + M.fault(__FILE__, __LINE__); } else { gpr = static_cast(op.get()); @@ -347,7 +347,7 @@ void Connection::handle_GPR(pva_app_msg_t cmd) } else if((gpr->state==GPROp::Exec) && !init && !get) { } else { - M.fault(); + M.fault(__FILE__, __LINE__); } } } diff --git a/src/clientmon.cpp b/src/clientmon.cpp index 9a4e71f..94630ba 100644 --- a/src/clientmon.cpp +++ b/src/clientmon.cpp @@ -411,7 +411,7 @@ void Connection::handle_MONITOR() if(uint8_t(op->op)!=CMD_MONITOR) { // peer mixes up IOID and operation type - M.fault(); + M.fault(__FILE__, __LINE__); } else { mon = static_cast(op.get()); @@ -424,7 +424,7 @@ void Connection::handle_MONITOR() } else if((mon->state==SubscriptionImpl::Running) && !init) { } else { - M.fault(); + M.fault(__FILE__, __LINE__); } } } diff --git a/src/dataencode.cpp b/src/dataencode.cpp index e184a0f..01be436 100644 --- a/src/dataencode.cpp +++ b/src/dataencode.cpp @@ -69,7 +69,7 @@ void to_wire(Buffer& buf, const FieldDesc* cur) void from_wire(Buffer& buf, std::vector& descs, TypeStore& cache, unsigned depth) { if(!buf.good() || depth>20) { - buf.fault(); + buf.fault(__FILE__, __LINE__); return; } @@ -86,7 +86,7 @@ void from_wire(Buffer& buf, std::vector& descs, TypeStore& cache, uns from_wire(buf, key); from_wire(buf, descs, cache, depth+1u); if(!buf.good() || index==descs.size()) { - buf.fault(); + buf.fault(__FILE__, __LINE__); return; } else { @@ -106,11 +106,11 @@ void from_wire(Buffer& buf, std::vector& descs, TypeStore& cache, uns from_wire(buf, key); auto it = cache.find(key); if(it==cache.end()) { - buf.fault(); + buf.fault(__FILE__, __LINE__); } if(!buf.good() || it->second.empty()) { - buf.fault(); + buf.fault(__FILE__, __LINE__); return; } else { @@ -123,7 +123,7 @@ void from_wire(Buffer& buf, std::vector& descs, TypeStore& cache, uns } else if(code.code!=0xff && code.code&0x10) { // fixed length is deprecated - buf.fault(); + buf.fault(__FILE__, __LINE__); } else { // actual field @@ -140,7 +140,7 @@ void from_wire(Buffer& buf, std::vector& descs, TypeStore& cache, uns case TypeCode::UnionA: from_wire(buf, descs.back().members, cache, depth+1); if(!buf.good() || descs.back().members.empty() || descs.back().members[0].code!=code.scalarOf()) { - buf.fault(); + buf.fault(__FILE__, __LINE__); return; } break; @@ -168,7 +168,7 @@ void from_wire(Buffer& buf, std::vector& descs, TypeStore& cache, uns from_wire(buf, name); from_wire(buf, cdescs, cache, depth+1); if(!buf.good() || cindex>=cdescs.size()) { - buf.fault(); + buf.fault(__FILE__, __LINE__); return; } @@ -211,7 +211,7 @@ void from_wire(Buffer& buf, std::vector& descs, TypeStore& cache, uns case TypeCode::Any: break; default: - buf.fault(); + buf.fault(__FILE__, __LINE__); break; } } @@ -435,7 +435,7 @@ void to_wire_field(Buffer& buf, const FieldDesc* desc, const std::shared_ptr evsocket::interfaces(const SockAddr* match) void to_wire(Buffer& buf, const SockAddr& val) { if(!buf.ensure(16)) { - buf.fault(); + buf.fault(__FILE__, __LINE__); return; } else if(val.family()==AF_INET) { @@ -476,7 +476,7 @@ void to_wire(Buffer& buf, const SockAddr& val) void from_wire(Buffer &buf, SockAddr& val) { if(!buf.ensure(16)) { - buf.fault(); + buf.fault(__FILE__, __LINE__); return; } diff --git a/src/pvaproto.h b/src/pvaproto.h index 5e7b778..25544c1 100644 --- a/src/pvaproto.h +++ b/src/pvaproto.h @@ -36,11 +36,14 @@ struct PVXS_API Buffer { protected: // valid range to read/write is [pos, limit) uint8_t *pos, *limit; - bool err; + + // this is a static __FILE__ string + const char* err = nullptr; + int errline = -1; virtual bool refill(size_t more); - constexpr Buffer(bool be, uint8_t* buf, size_t n) :pos(buf), limit(buf+n), err(false), be(be) {} + constexpr Buffer(bool be, uint8_t* buf, size_t n) :pos(buf), limit(buf+n), be(be) {} virtual ~Buffer() {} public: const bool be; @@ -48,14 +51,19 @@ public: // all sub-classes define // bool refill(size_t more) - EPICS_ALWAYS_INLINE void fault() { err = true; } + // would be nice to use GCC specific __builtin_FILE() and __builtin_LINE() here, + // but MSVC has nothing equivalent :( + EPICS_ALWAYS_INLINE void fault(const char *fname, int lineno) { + err = fname; + errline = lineno; + } EPICS_ALWAYS_INLINE bool good() const { return !err; } // ensure (be resize/refill) that size()>=i inline bool ensure(size_t i) { return !err && (i<=size() || refill(i)); } - inline void skip(size_t i) { + inline void skip(size_t i, const char *fname, int lineno) { do { if(i<=size()) { pos += i; @@ -64,7 +72,7 @@ public: pos = limit; i -= size(); } while(refill(i)); - fault(); + fault(fname, lineno); } EPICS_ALWAYS_INLINE bool empty() const { return limit==pos; } @@ -152,7 +160,7 @@ template inline void _to_wire(Buffer& buf, const uint8_t *mem, bool reverse) { if(!buf.ensure(N)) { - buf.fault(); + buf.fault(__FILE__, __LINE__); return; } else if(reverse) { @@ -172,7 +180,7 @@ template inline void _from_wire(Buffer& buf, uint8_t *mem, bool reverse) { if(!buf.ensure(N)) { - buf.fault(); + buf.fault(__FILE__, __LINE__); return; } else if(reverse) { @@ -208,7 +216,7 @@ template:: inline void to_wire(Buffer& buf, const T& val) { if(!buf.ensure(1)) { - buf.fault(); + buf.fault(__FILE__, __LINE__); } else { buf.push(val); } @@ -249,7 +257,7 @@ inline void to_wire(Buffer& buf, const Size& size) { if(!buf.ensure(1)) { - buf.fault(); + buf.fault(__FILE__, __LINE__); } else if(size.size<254) { buf.push(uint8_t(size.size)); @@ -263,7 +271,7 @@ void to_wire(Buffer& buf, const Size& size) buf.push(255); } else { - buf.fault(); + buf.fault(__FILE__, __LINE__); } } @@ -271,7 +279,7 @@ inline void from_wire(Buffer& buf, Size& size) { if(!buf.ensure(1)) { - buf.fault(); + buf.fault(__FILE__, __LINE__); return; } uint8_t s=buf.pop(); @@ -289,7 +297,7 @@ void from_wire(Buffer& buf, Size& size) } else { // unreachable (64-bit size so far not used) - buf.fault(); + buf.fault(__FILE__, __LINE__); } } @@ -299,7 +307,7 @@ void to_wire(Buffer& buf, const char *s) Size len{s ? strlen(s) : 0}; to_wire(buf, len); if(!buf.ensure(len.size)) { - buf.fault(); + buf.fault(__FILE__, __LINE__); } else { for(size_t i=0; i bytes) { if(!buf.ensure(bytes.size())) { - buf.fault(); + buf.fault(__FILE__, __LINE__); } else { for (auto byte : bytes) { @@ -366,7 +374,7 @@ inline void to_wire(Buffer& buf, const Status& sts) { if(!buf.ensure(1)) { - buf.fault(); + buf.fault(__FILE__, __LINE__); } else if(sts.code==Status::Ok && sts.msg.empty() && sts.trace.empty()) { buf.push(255); @@ -382,7 +390,7 @@ inline void from_wire(Buffer& buf, Status& sts) { if(!buf.ensure(1)) { - buf.fault(); + buf.fault(__FILE__, __LINE__); } else if(255==buf[0]) { buf._skip(1); @@ -486,7 +494,7 @@ template void to_wire(Buf& buf, const Header& H) { if(!buf.ensure(8)) { - buf.fault(); + buf.fault(__FILE__, __LINE__); } else { buf[0] = 0xca; diff --git a/src/server.cpp b/src/server.cpp index 4f67df9..8d4fb34 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -548,7 +548,7 @@ void Server::Pvt::onSearch(const UDPManager::Search& msg) VectorOutBuf M(true, searchReply); - M.skip(8); // fill in header after body length known + M.skip(8, __FILE__, __LINE__); // fill in header after body length known _to_wire<12>(M, effective.guid.data(), false); to_wire(M, msg.searchID); @@ -581,7 +581,7 @@ void Server::Pvt::doBeacons(short evt) log_debug_printf(serversetup, "Server beacon timer expires\n%s", ""); VectorOutBuf M(true, beaconMsg); - M.skip(8); // fill in header after body length known + M.skip(8, __FILE__, __LINE__); // fill in header after body length known _to_wire<12>(M, effective.guid.data(), false); to_wire(M, uint8_t(0u)); // flags (aka. QoS, aka. undefined) diff --git a/src/serverchan.cpp b/src/serverchan.cpp index e822c93..5958063 100644 --- a/src/serverchan.cpp +++ b/src/serverchan.cpp @@ -194,7 +194,7 @@ void ServerConn::handle_SEARCH() from_wire(M, searchID); from_wire(M, flags); bool mustReply = flags&pva_search_flags::MustReply; - M.skip(3 + 16 + 2); // unused and replyAddr (we always and only reply to TCP peer) + M.skip(3 + 16 + 2, __FILE__, __LINE__); // unused and replyAddr (we always and only reply to TCP peer) bool foundtcp = false; Size nproto{0}; @@ -348,7 +348,7 @@ void ServerConn::handle_CREATE_CHANNEL() to_wire(R, sts); // "spec" calls for uint16_t Access Rights here, but pvAccessCPP don't include this (it's useless anyway) if(!R.good()) { - M.fault(); + M.fault(__FILE__, __LINE__); log_err_printf(connio, "Client %s Encode error in CreateChan\n", peerName.c_str()); break; } diff --git a/src/serverconn.cpp b/src/serverconn.cpp index e7bc079..675be30 100644 --- a/src/serverconn.cpp +++ b/src/serverconn.cpp @@ -50,7 +50,7 @@ ServerConn::ServerConn(ServIface* iface, evutil_socket_t sock, struct sockaddr * to_wire(M, Header{pva_ctrl_msg::SetEndian, pva_flags::Control|pva_flags::Server, 0}); auto save = M.save(); - M.skip(8); // placeholder for header + M.skip(8, __FILE__, __LINE__); // placeholder for header auto bstart = M.save(); // serverReceiveBufferSize, not used @@ -128,7 +128,7 @@ void ServerConn::handle_CONNECTION_VALIDATION() std::string selected; { - M.skip(4+2+2); // ignore unused buffer, introspection size, and QoS + M.skip(4+2+2, __FILE__, __LINE__); // ignore unused buffer, introspection size, and QoS from_wire(M, selected); Value auth; diff --git a/src/udp_collector.cpp b/src/udp_collector.cpp index 24d88b4..9be8443 100644 --- a/src/udp_collector.cpp +++ b/src/udp_collector.cpp @@ -96,7 +96,7 @@ struct UDPCollector : public UDPManager::Search, uint8_t cmd = M[3]; - M.skip(4); + M.skip(4, __FILE__, __LINE__); uint32_t len=0; from_wire(M, len); @@ -117,7 +117,7 @@ struct UDPCollector : public UDPManager::Search, from_wire(M, searchID); from_wire(M, flags); mustReply = flags&pva_search_flags::MustReply; - M.skip(3); // unused/reserved + M.skip(3, __FILE__, __LINE__); // unused/reserved from_wire(M, replyAddr); from_wire(M, port); @@ -138,7 +138,7 @@ struct UDPCollector : public UDPManager::Search, // shortcut to avoid allocating a std::string // "tcp" is the only value we expect to see foundtcp |= M.size()>=3 && nchar.size==3 && M[0]=='t' && M[1]=='c' && M[2]=='p'; - M.skip(nchar.size); + M.skip(nchar.size, __FILE__, __LINE__); } // one Search message can include many PV names. @@ -160,7 +160,7 @@ struct UDPCollector : public UDPManager::Search, if(foundtcp && chlen.size<=M.size() && M.good()) { names.push_back(UDPManager::Search::Name{reinterpret_cast(M.save()), id}); } - M.skip(chlen.size); + M.skip(chlen.size, __FILE__, __LINE__); } if(M.good()) { @@ -181,7 +181,7 @@ struct UDPCollector : public UDPManager::Search, uint16_t port = 0; _from_wire<12>(M, &beaconMsg.guid[0], false); - M.skip(4); // skip flags, seq, and change count. unused + M.skip(4, __FILE__, __LINE__); // skip flags, seq, and change count. unused from_wire(M, beaconMsg.server); from_wire(M, port); if(beaconMsg.server.isAny()) { @@ -191,7 +191,7 @@ struct UDPCollector : public UDPManager::Search, Size protolen{0}; from_wire(M, protolen); - M.skip(protolen.size); // ignore string + M.skip(protolen.size, __FILE__, __LINE__); // ignore string // ignore remaining "server status" blob diff --git a/test/testudp.cpp b/test/testudp.cpp index ec53f66..91ef3ab 100644 --- a/test/testudp.cpp +++ b/test/testudp.cpp @@ -116,9 +116,9 @@ void testSearch(bool be, std::initializer_list names) std::vector msg(1024, 0); VectorOutBuf M(be, msg); - M.skip(8); // placeholder for header + M.skip(8, __FILE__, __LINE__); // placeholder for header to_wire(M, uint32_t(0x12345678)); - M.skip(4); + M.skip(4, __FILE__, __LINE__); SockAddr reply(SockAddr::any(AF_INET, 0x1020)); to_wire(M, reply); to_wire(M, uint16_t(reply.port()));