DataLakeDirectoryClient::ListPaths() throws exception due to incorrect format used for date-time fields
I maintainer di solito rispondono entro 1 giorno
@Jinming-Hu ci sta già lavorando.
Dal 2/10/2026.
Valutazione
Questa issue non è ancora stata valutata.
Descrizione
Title
DataLakeDirectoryClient::ListPaths() throws exception due to incorrect format used for date-time fields
Describe the bug
Azure::Storage::Files::DataLake::DataLakeDirectoryClient::ListPaths()
throws std::invalid_argument (what() == "stoll") on completely
well-formed, valid ADLS Gen2 ListPaths REST responses, whenever the
server returns the creationTime/expiryTime path-property fields as
RFC1123 date-time text rather than a numeric Win32 FILETIME string.
Root cause: in DataLakeDirectoryClient::ListPaths()
(sdk/storage/azure-storage-files-datalake/src/datalake_directory_client.cpp),
the loop that copies protocol-layer _detail::PathItem results into the
public Models::PathItem results unconditionally assumes
creationTime/expiryTime are numeric Win32 FILETIME strings (100-ns
ticks since 1601-01-01) and calls std::stoll() directly on them:
if (path.CreatedOn.HasValue())
{
item.CreatedOn = _detail::Win32FileTimeConverter::Win32FileTimeToDateTime(
std::stoll(path.CreatedOn.Value()));
}
if (path.ExpiresOn.HasValue() && path.ExpiresOn.Value() != "0")
{
item.ExpiresOn = _detail::Win32FileTimeConverter::Win32FileTimeToDateTime(
std::stoll(path.ExpiresOn.Value()));
}
However, for at least some accounts/API versions, the server instead
returns these fields pre-formatted as RFC1123 date-time text — the
exact same textual format used for the lastModified field, which the
protocol layer (rest_client.cpp) parses correctly a few lines earlier
via DateTime::Parse(var0["lastModified"].get<std::string>(), Azure::DateTime::DateFormat::Rfc1123). When creationTime/expiryTime
are present in this text form (e.g. "Fri, 11 Oct 2019 22:32:19 GMT"),
std::stoll() immediately throws std::invalid_argument, aborting the
entire ListPaths() call for the whole page of results — even though the
response is completely well-formed, and the sibling
FileSystemClient::ListPaths() call (which never derives a DateTime
from creationTime/expiryTime at all) handles the identical response
bytes without any issue.
Exception or Stack Trace
terminate called after throwing an instance of 'std::invalid_argument'
what(): stoll
Reproduced 100% deterministically (unlike the related UB-driven bug
reported separately in BUG-REPORT-1-owner-group-permissions-UB.md) —
every single call against the affected account/filesystem throws this
exact exception, because std::stoll() is being handed non-numeric text.
To Reproduce
Steps to reproduce the behavior:
- Use (or point at) an ADLS Gen2 account/filesystem whose
ListPaths
REST responses returncreationTime/expiryTimeas RFC1123 text
rather than a numeric FILETIME string (observed consistently against a
production Azure Storage account in our testing). - Call
DataLakeDirectoryClient::ListPaths()(e.g. via
DataLakeDirectoryClient(...).ListPaths(recursive, options)) against
any directory in that filesystem that has at least one path with a
creationTime/expiryTimevalue present in the response. - Observe
std::invalid_argument("stoll") thrown on every call,
preventing any results from ever being returned — even though the raw
HTTP response is valid, well-formed JSON.
A raw, captured ListPaths response we observed that reliably triggers
this (with contentLength sometimes present as a numeric-looking string
too, per Bug 1's separate contentLength handling):
{"paths":[
{
"contentLength":"82372",
"creationTime":"Fri, 11 Oct 2019 22:32:19 GMT",
"etag":"0x8D74E9AE06DE5D2",
"lastModified":"Fri, 11 Oct 2019 22:32:19 GMT",
"name":"data/archive/archive.json.gz"
}
]}
Independently re-parsing this exact JSON with a fresh json::parse()
call succeeds cleanly (every field a string, creationTime and
lastModified both valid RFC1123 text) — yet
DataLakeDirectoryClient::ListPaths() throws on every call against it,
100% reproducibly, because of the unconditional
std::stoll(path.CreatedOn.Value()).
Code Snippet
The buggy code, in
sdk/storage/azure-storage-files-datalake/src/datalake_directory_client.cpp,
DataLakeDirectoryClient::ListPaths():
item.Permissions = std::move(path.Permissions);
item.EncryptionScope = std::move(path.EncryptionScope);
item.ETag = std::move(path.ETag);
if (path.CreatedOn.HasValue())
{
item.CreatedOn = _detail::Win32FileTimeConverter::Win32FileTimeToDateTime(
std::stoll(path.CreatedOn.Value()));
}
if (path.ExpiresOn.HasValue() && path.ExpiresOn.Value() != "0")
{
item.ExpiresOn = _detail::Win32FileTimeConverter::Win32FileTimeToDateTime(
std::stoll(path.ExpiresOn.Value()));
}
item.EncryptionContext = std::move(path.EncryptionContext);
A minimal, standalone repro of just the failing conversion:
#include <string>
#include <stdexcept>
long long ToFileTime(const std::string& raw) {
// Throws std::invalid_argument("stoll") when raw is RFC1123 text
// instead of a numeric FILETIME string, e.g. "Fri, 11 Oct 2019 22:32:19 GMT".
return std::stoll(raw);
}
int main() {
ToFileTime("Fri, 11 Oct 2019 22:32:19 GMT"); // throws immediately
}
Expected behavior
ListPaths() should handle both representations the ADLS Gen2 service may
return for creationTime/expiryTime — numeric Win32 FILETIME strings
and RFC1123 date-time text (the same format already handled for
lastModified) — by detecting which format was actually returned before
choosing how to convert it to a DateTime, rather than assuming FILETIME
unconditionally. It should never throw an uncaught, undifferentiated
std::invalid_argument for a well-formed, documented server response.
Screenshots
Not applicable (this is a backend/library exception, not a UI issue).
Setup (please complete the following information):
- OS: SUSE Linux Enterprise Server 15 SP7 (
SLES 15-SP7, x86_64); also
expected to reproduce on any platform, since the bug is in
platform-independent deserialization code - IDE: N/A (reproduced via a standalone C++ test harness, not an IDE)
- Compiler/toolchain: GCC 14.3.0, CMake 3.28.3
- Version of the Library used:
azure-storage-files-datalake12.15.0
(root cause confirmed still present by source inspection of the current
mainbranch ofazure-sdk-for-cppas of this report)
Additional context
- This bug was discovered while investigating a customer-reported issue in
which aCREATE FOREIGN TABLE-style directory listing against a
container containing archive-tier blobs (Azure Blob Storage) surfaced a
confusing client-side deserialization error instead of the correct,
expected409"operation not permitted on an archived blob" server
error. This bug was masked behind a separate, independent bug (filed
separately — seeBUG-REPORT-1-owner-group-permissions-UB.md— an
undefined-behavior/UB issue reading optionalowner/group/
permissions/contentLengthfields in the sibling
FileSystemClient::ListPaths()protocol-layer function) which, being
nondeterministic, sometimes fired first and masked this deterministic
bug entirely. Once Bug 1 was fixed in isolation, this bug then surfaced
100% reproducibly on every single call. - We'd suggest double-checking whether other date/time fields elsewhere in
the DataLake (and possibly Blob) client code make the same
FILETIME-only assumption without considering the RFC1123-text
possibility, since both formats are apparently valid depending on
account/API-version/response path. - A minimal, self-contained fix is attached as a unified diff:
NOS-14641-createdon-expireson-format-guard.patch. Full before/after
source is also attached:datalake_directory_client.cpp.orig/
datalake_directory_client.cpp.patched. The fix detects an all-digit
string (FILETIME) vs. text (RFC1123, parsed via
Azure::DateTime::DateFormat::Rfc1123, consistent with how
lastModifiedis already parsed) before converting, and was built and
verified end-to-end against a live Azure Storage account whose
ListPathsresponses previously triggered this bug on every call.
Information Checklist
Kindly make sure that you have added all the following information above
and checkoff the required fields otherwise we will treat the issuer as an
incomplete report
- Bug Description Added
- Repro Steps Added
- Setup information Added
- Lingua principale
- C++
- Stelle
- 206
- Fork
- 177
- Merge medio
- 2g 17h
- PR unite (30g)
- 37
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 25 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
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
elf-alchemist/elfbsp#113 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
patrick-hudson/put.gd-desktop#979 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
Dao-AILab/flash-attention#3097 ·
I maintainer di solito rispondono entro 3 giorni
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 85/100
Niko1221/Strata#4779 · 2 commenti ·
I maintainer di solito rispondono entro 3 giorni
-
tech-debt
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
prestonbrown/helixscreen#1990 ·
I maintainer di solito rispondono entro 1 giorno