microsoft / microsoft/STL

`<exception>`: constructor does not copy what_arg if `_HAS_EXCEPTIONS=0`

Open
#2,114 6 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug vNext
Dominant language
C++
Stars
11.1k
Forks
1.7k
Avg merge
4d 15h
Merged PRs (30d)
22

Description

Describe the bug

When _HAS_EXCEPTIONS is defined to 0, the constructors of the exception classes do not copy the what_arg, but only store the pointer: https://github.com/microsoft/STL/blob/472161105d596192194d4715ccad307c6c163b4a/stl/inc/exception#L90

This leads to errors if the pointee is a temporary string.

If _HAS_EXCEPTIONS is set to 1, a copy is made just as the standard would require it.

Command-line test case

The following code outputs [json.exception.parse_error] foo if _HAS_EXCEPTIONS is set to 1, and some garbage if _HAS_EXCEPTIONS is set to 0:

#include <exception> // exception
#include <stdexcept> // runtime_error
#include <string> // string
#include <iostream> // cout

namespace nlohmann
{
namespace detail2
{

class exception : public std::exception
{
  public:
    const char* what() const noexcept override
    {
        return m.what();
    }

  protected:
    exception(const char* what_arg) : m(what_arg) {}

  private:
    std::runtime_error m;
};

class parse_error : public exception
{
  public:
    static parse_error create(const std::string& what_arg)
    {
        std::string w = "[json.exception.parse_error] " + what_arg;
        return parse_error(w.c_str());
    }

  private:
    parse_error(const char* what_arg) : exception(what_arg) {}
};

}  // namespace detail2
}  // namespace nlohmann


int main()
{
    auto error = nlohmann::detail2::parse_error::create("foo");
    std::cout << error.what() << std::endl;
}

The example comes from https://github.com/nlohmann/json where exceptions are created by a SAX parser, but it is up to the client whether they are thrown or not. Therefore, using exception classes while disabling throwing exceptions is a usecase.

Expected behavior

The exception makes a copy of the what_arg argument, regardless of the value of _HAS_EXCEPTIONS.

STL version

I could reproduce the issue with MSVC 19.16.27045.0 and MSVC 19.29.30040.0.

Additional context

The issue was originally found here: https://github.com/nlohmann/json/discussions/2824

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with stl/inc/exception and reproduce the command-line example with _HAS_EXCEPTIONS set to 0 and 1. Inspect how the exception constructors retain what_arg, then add regression coverage showing that what() remains valid for a temporary string in both configurations; done means the output is stable and matches the expected message.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
backend
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.