RequestFailedException loses its message when it is copied
I maintainer di solito rispondono entro 1 giorno
Valutazione
- Difficoltà
- 3/5
- Tempo stimato
- 1-2 giorni
- Idoneità per principianti
- 78/100
Direzione di ricerca
Inizia da sdk/core/azure-core/inc/azure/core/exception.hpp e sdk/core/azure-core/src/exception.cpp, quindi esamina i percorsi raw-response in sdk/storage/azure-storage-common/src/storage_exception.cpp e gli header delle eccezioni derivate. Aggiungi i test di copia proposti per i costruttori string e raw-response, TransportException e StorageException; il lavoro è completato quando what() viene preservato, inclusi i dettagli della risposta, e il changelog indica che i consumer devono ricompilare.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Summary
Azure::Core::RequestFailedException builds a copy from its Message field, and not from the result of what(). The string constructor never sets Message. A copy of an exception that the string constructor built therefore returns an empty string from what().
Each class that derives from RequestFailedException inherits the defect. Azure::Storage::StorageException is one example.
Motivation
Two functions produce the defect together.
The string constructor sets the base class and leaves Message empty (sdk/core/azure-core/src/exception.cpp:20-22):
RequestFailedException::RequestFailedException(std::string const& what) : std::runtime_error(what)
{
}
The copy constructor builds the base class from other.Message (sdk/core/azure-core/inc/azure/core/exception.hpp:144-153):
RequestFailedException(const RequestFailedException& other)
: std::runtime_error(other.Message),
RawResponse(...),
StatusCode(other.StatusCode), ReasonPhrase(other.ReasonPhrase),
ClientRequestId(other.ClientRequestId), RequestId(other.RequestId),
ErrorCode(other.ErrorCode), Message(other.Message)
A copy therefore replaces the text of what() with the text of Message.
A minimal reproduction
This program mirrors the two functions above. It needs no build of the SDK.
#include <cstdio>
#include <stdexcept>
#include <string>
class RequestFailedException : public std::runtime_error {
public:
std::string Message;
// exception.cpp:20-22 -- this constructor does not set Message.
explicit RequestFailedException(std::string const& what) : std::runtime_error(what) {}
// exception.hpp:144-153 -- this constructor reads other.Message, not other.what().
RequestFailedException(const RequestFailedException& other)
: std::runtime_error(other.Message), Message(other.Message)
{
}
};
int main()
{
RequestFailedException original("connection reset by peer");
RequestFailedException copy(original);
std::printf("original.what() = \"%s\"\n", original.what());
std::printf("copy.what() = \"%s\"\n", copy.what());
return 0;
}
The output shows the loss:
original.what() = "connection reset by peer"
copy.what() = ""
The raw response path also changes
The defect is not limited to an empty result. StorageException::CreateFromResponse gives the two fields different text (sdk/storage/azure-storage-common/src/storage_exception.cpp:158-167). It builds what() from the status code, the reason phrase, the service message, and the request ID. It sets Message to the service message alone. A copy of that exception removes the status code, the reason phrase, and the request ID from what().
The RequestFailedException raw response constructor has the same shape (sdk/core/azure-core/src/exception.cpp:24-37). It builds the base class from GetRawResponseErrorMessage, and it sets Message from the message field of the response body. A response body without a message field gives an empty Message, and a copy then gives an empty what().
When a copy occurs
A copy occurs when a caller catches the exception by value, when code throws a named exception object, or when code stores the exception for later use. A search of this repository finds no catch by value site today. The defect therefore affects consumer code and new SDK code, and not a current SDK code path. This is the reason that this issue is not a release blocker.
The types that the defect reaches
RequestFailedException is the only exception type in this repository with a hand-written copy constructor. Each other type uses the implicit copy constructor, and each of those types copies correctly.
Azure::Core::Http::TransportExceptionderives fromRequestFailedException(sdk/core/azure-core/inc/azure/core/http/http.hpp:57). It inherits the defect.Azure::Storage::StorageExceptionderives fromRequestFailedException(sdk/storage/azure-storage-common/inc/azure/storage/common/storage_exception.hpp:19). It inherits the defect.Azure::Core::OperationCancelledExceptionderives fromstd::runtime_error, and it holds no separate message field (sdk/core/azure-core/inc/azure/core/context.hpp:32). It copies correctly.Azure::Core::Credentials::AuthenticationExceptionderives fromstd::exception, and it holds the text instd::string m_what(sdk/core/azure-core/inc/azure/core/credentials/credentials.hpp:139-158). It copies correctly.
Related work
#7273 adds a new Azure Core exception type for a protocol that is not HTTP, and it derives Azure::Messaging::EventHubs::EventHubsException from that new type. The new type must not repeat this defect. EventHubsException copies correctly today, because it derives from std::runtime_error and it declares no copy constructor (sdk/eventhubs/azure-messaging-eventhubs/inc/azure/messaging/eventhubs/eventhubs_exception.hpp:19).
An alternative that this issue does not propose
The string constructor could set Message from its what parameter. That change makes the two fields hold the same text, and the documentation of Message states a different purpose: it holds the message that the service returned in the HTTP response. The copy constructor is the correct place for the fix.
Proposal
- Build the base class from
other.what()in the copy constructor (sdk/core/azure-core/inc/azure/core/exception.hpp:144-153). - Add a test that copies an exception from the string constructor. The test compares
what()before the copy and after the copy. - Add a test that copies an exception from the raw response constructor, and that makes the same comparison.
- Add a copy test for
TransportExceptionand forStorageException. Both types inherit the defect from the base class.
The copy constructor is inline in an installed header, so a consumer who links a prebuilt binary must rebuild to get the corrected behavior. Record that expectation in the change log entry.
Validation
-
what()returns the same text before a copy and after a copy, for each constructor. - The new tests fail against the current code, and they pass after the change.
-
StorageExceptionkeeps the status code, the reason phrase, and the request ID inwhat()after a copy. -
TransportExceptionkeeps the text ofwhat()after a copy.
- Lingua principale
- C++
- Stelle
- 206
- Fork
- 177
- Merge medio
- 2g 6h
- PR unite (30g)
- 35
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di Azure/azure-sdk-for-cpp
-
bug EngSys
Difficoltà 2/5 1-3 ore Idoneità per principianti 86/100
Azure/azure-sdk-for-cpp#7362 ·
I maintainer di solito rispondono entro 1 giorno
-
Client needs-team-attention Service Attention Storage
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
Azure/azure-sdk-for-cpp#7347 · 2 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
Client Event Hubs needs-team-attention Service Attention
Difficoltà 2/5 1-3 ore Idoneità per principianti 86/100
Azure/azure-sdk-for-cpp#7333 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Azure Storage STG105 Feature TestsForse già presa @Jinming-Hu l’ha presa 19 giorni fa. ApertaClient Storage
Azure/azure-sdk-for-cpp#7449 · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
-
Azure.Core bug test-enhancement
Difficoltà 3/5 1-2 giorni Idoneità per principianti 66/100
Azure/azure-sdk-for-cpp#7401 ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di Azure/azure-sdk-for-cpp
Issue simili
-
Remove source files from packaging for deb, zip, etcForse già presa Una pull request collegata a questa issue è aperta o già unita. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 85/100
OpenSpace/OpenSpace#4353 · 1 commento ·
I maintainer di solito rispondono entro 5 giorni
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 86/100
justcallmekoko/ESP32Marauder#1656 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
-
Decompiler: convertCharRef() in xml.y overflows its int4 accumulator on long character referencesForse già presa @kaayzouee l’ha presa 1 giorno fa. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
NationalSecurityAgency/ghidra#10009 ·
I maintainer di solito rispondono entro 2 giorni
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
mutationpp/Mutationpp#337 ·