comparison Framework/Oracle/WebAssemblyOracle.cpp @ 975:e75fd08d6c75 toa2019083101

Cleaning in ICallable + changed fingerprint to plain char array to allow for dead object examination + additional check in FetchContext callback to avoid the unexplained rogue callbacks I have seen + protection in LoaderStateMachine::HandleSuccessMessage in case things go wrong anyway
author Benjamin Golinvaux <bgo@osimis.io>
date Sat, 31 Aug 2019 13:45:04 +0200
parents 38409549db43
children 262a0244e9b2
comparison
equal deleted inserted replaced
974:e4b028c1ede1 975:e75fd08d6c75
97 class WebAssemblyOracle::FetchContext : public boost::noncopyable 97 class WebAssemblyOracle::FetchContext : public boost::noncopyable
98 { 98 {
99 private: 99 private:
100 Emitter emitter_; 100 Emitter emitter_;
101 const IObserver& receiver_; 101 const IObserver& receiver_;
102 std::string receiverFingerprint_;
103 std::auto_ptr<IOracleCommand> command_; 102 std::auto_ptr<IOracleCommand> command_;
104 std::string expectedContentType_; 103 std::string expectedContentType_;
105 104
106 public: 105 public:
107 FetchContext(WebAssemblyOracle& oracle, 106 FetchContext(WebAssemblyOracle& oracle,
108 const IObserver& receiver, 107 const IObserver& receiver,
109 IOracleCommand* command, 108 IOracleCommand* command,
110 const std::string& expectedContentType) : 109 const std::string& expectedContentType) :
111 emitter_(oracle), 110 emitter_(oracle),
112 receiver_(receiver), 111 receiver_(receiver),
113 receiverFingerprint_(receiver.GetFingerprint()),
114 command_(command), 112 command_(command),
115 expectedContentType_(expectedContentType) 113 expectedContentType_(expectedContentType)
116 { 114 {
117 if (command == NULL) 115 if (command == NULL)
118 { 116 {
119 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); 117 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
120 } 118 }
121 }
122
123 bool IsFingerprintOK() const
124 {
125 bool ok = receiverFingerprint_ == receiver_.GetFingerprint();
126 if (!ok)
127 {
128 LOG(TRACE) << "IsFingerprintOK returned false. receiverFingerprint_ = " << receiverFingerprint_ << " | receiver_(" << std::hex << (&receiver_) << std::dec << ").GetFingerprint() = " << receiver_.GetFingerprint();
129 }
130 return ok;
131 } 119 }
132 120
133 const std::string& GetExpectedContentType() const 121 const std::string& GetExpectedContentType() const
134 { 122 {
135 return expectedContentType_; 123 return expectedContentType_;
205 * Firstly, make a local copy of the fetched information, and 193 * Firstly, make a local copy of the fetched information, and
206 * free data associated with the fetch. 194 * free data associated with the fetch.
207 **/ 195 **/
208 196
209 std::auto_ptr<FetchContext> context(reinterpret_cast<FetchContext*>(fetch->userData)); 197 std::auto_ptr<FetchContext> context(reinterpret_cast<FetchContext*>(fetch->userData));
198
199 // an UUID is 36 chars : 32 hex chars + 4 hyphens: char #0 --> char #35
200 // char #36 is \0.
201
202 // TODO: remove this line because we are NOT allowed to call methods on GetReceiver that is maybe a dangling ref
203 if (context->GetReceiver().DoesFingerprintLookGood()) {
204 LOG(TRACE) << "SuccessCallback for object at address (" << std::hex << &(context->GetReceiver()) << std::dec << " with current fingerprint = " << context->GetReceiver().GetFingerprint();
205 }
206 else {
207 LOG(TRACE) << "SuccessCallback for object at address (" << std::hex << &(context->GetReceiver()) << std::dec << " with current fingerprint is XXXXX -- NOT A VALID FINGERPRINT! OBJECT IS READ ! CALLBACK WILL NOT BE CALLED!";
208 }
209
210 210
211 if (fetch->userData == NULL) 211 if (fetch->userData == NULL)
212 { 212 {
213 LOG(ERROR) << "WebAssemblyOracle::FetchContext::SuccessCallback fetch->userData is NULL!!!!!!!"; 213 LOG(ERROR) << "WebAssemblyOracle::FetchContext::SuccessCallback fetch->userData is NULL!!!!!!!";
214 } 214 }
241 if (context->GetCommand().GetType() == IOracleCommand::Type_OrthancRestApi) { 241 if (context->GetCommand().GetType() == IOracleCommand::Type_OrthancRestApi) {
242 //if (logbgo115) 242 //if (logbgo115)
243 DumpCommand(fetch, answer); 243 DumpCommand(fetch, answer);
244 } 244 }
245 #endif 245 #endif
246 LOG(TRACE) << "About to call emscripten_fetch_close";
246 emscripten_fetch_close(fetch); 247 emscripten_fetch_close(fetch);
248 LOG(TRACE) << "Successfully called emscripten_fetch_close";
247 249
248 /** 250 /**
249 * Secondly, use the retrieved data. 251 * Secondly, use the retrieved data.
250 * We only use the receiver if its fingerprint matches the one stored 252 * IMPORTANT NOTE: the receiver might be dead. This is prevented
251 * at command creation. 253 * by the object responsible for zombie check, later on.
252 **/ 254 **/
253 if (!context->IsFingerprintOK()) 255 try
254 { 256 {
255 LOG(WARNING) << "FetchContext::SuccessCallback -- the initial request initiator has been destroyed. Response will be discarded."; 257 if (context.get() == NULL)
256 }
257 else
258 {
259 try
260 { 258 {
261 if (context.get() == NULL) 259 LOG(ERROR) << "WebAssemblyOracle::FetchContext::SuccessCallback: (context.get() == NULL)";
262 { 260 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
263 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); 261 }
264 } 262 else
265 else 263 {
266 { 264 if (context->GetReceiver().DoesFingerprintLookGood()) {
267 switch (context->GetCommand().GetType()) 265 switch (context->GetCommand().GetType())
268 { 266 {
269 case IOracleCommand::Type_OrthancRestApi: 267 case IOracleCommand::Type_OrthancRestApi:
270 { 268 {
271 OrthancRestApiCommand::SuccessMessage message 269 OrthancRestApiCommand::SuccessMessage message
292 LOG(ERROR) << "Command type not implemented by the WebAssembly Oracle: " 290 LOG(ERROR) << "Command type not implemented by the WebAssembly Oracle: "
293 << context->GetCommand().GetType(); 291 << context->GetCommand().GetType();
294 } 292 }
295 } 293 }
296 } 294 }
297 catch (Orthanc::OrthancException& e) 295 }
298 { 296 catch (Orthanc::OrthancException& e)
299 LOG(ERROR) << "Error while processing a fetch answer in the oracle: " << e.What(); 297 {
300 } 298 LOG(ERROR) << "Error while processing a fetch answer in the oracle: " << e.What();
301 } 299 }
302 } 300 }
303 301
304 static void FailureCallback(emscripten_fetch_t *fetch) 302 static void FailureCallback(emscripten_fetch_t *fetch)
305 { 303 {