rastray 0.15.0

Blazing-fast static analysis CLI for security, dependency, and performance audits.
# RSTR-MEM-005 — raw `new` outside a smart pointer

## Summary

A raw `new TypeName(args)` allocation appears in C++ source. The
returned pointer is a bare `T *` — the language doesn't track who
owns it, who must `delete` it, or what happens if an exception
unwinds the stack between this allocation and the eventual `delete`.
Modern C++ (C++11+) provides `std::unique_ptr<T>` and
`std::shared_ptr<T>` for exactly this case: the smart pointer's
destructor frees the memory, exception-safety is automatic, and
ownership is visible at every call site.

This is rastray's first **`Confidence::Low`** rule: many codebases
have audited raw-`new` patterns (custom allocators, intrusive
reference counting, etc.) where the pattern is intentional. The
finding is heuristic — it can't tell from the call site alone whether
the result is wrapped in a smart pointer one line later. It surfaces
by default; tighten with `--min-confidence high` to filter it out
project-wide once you've audited.

## Severity

`Medium`. The damage is real (memory leak on the exception path) but
not directly exploitable — the runtime impact is degraded
performance over time, not arbitrary code execution.

## Confidence

`Low`. By design — see the rationale above. The intent is to surface
the pattern for review, not to block CI.

## Languages

C, C++ (`.c`, `.cc`, `.cpp`, `.cxx`, `.h`, `.hpp`, `.hh`, `.hxx`).

## What rastray flags

```cpp
auto *p = new Widget(args);                 // ← flagged
return new Foo{};                           // ← flagged
auto *s = new std::string("abc");           // ← flagged
char *buf = new char[size];                 // ← flagged
```

## What rastray deliberately does *not* flag

- Smart-pointer factory functions: `std::make_unique<T>(args)`,
  `std::make_shared<T>(args)`. These don't contain the literal
  `new ` keyword.
- Placement new (`new (buf) T(args)`) — different mechanism, doesn't
  allocate, can't leak.
- Operator-new overloads or custom allocators referenced via
  `T::operator new`.

## How to fix it

Use `std::make_unique` or `std::make_shared`:

```cpp
#include <memory>

auto p = std::make_unique<Widget>(args);    // unique ownership
auto p = std::make_shared<Foo>();           // shared ownership

// for arrays
auto buf = std::make_unique<char[]>(size);
```

Both forms release the allocation when the smart pointer goes out of
scope, even if an exception unwinds the stack between allocation and
the next statement. Ownership is visible: the type is
`std::unique_ptr<Widget>`, not a bare `Widget *`.

For very performance-sensitive cases where you've measured the
overhead, consider an arena allocator or `std::pmr::polymorphic_allocator`
rather than raw `new`.

## How to suppress

Per-line for an audited site:

```cpp
// rastray-ignore: RSTR-MEM-005 — placement allocator owns the lifetime
T *p = pool.allocate<T>(args);
```

Project-wide if your team has agreed on raw-`new` patterns:

```sh
rastray --min-confidence high
```

Or in `.rastray.toml`:

```toml
[rules]
"RSTR-MEM-005" = false
```

## References

- [C++ Core Guidelines R.11 — Avoid `new` and `delete`]https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rr-newdelete
- [`std::make_unique`]https://en.cppreference.com/w/cpp/memory/unique_ptr/make_unique
- [CWE-401 — Memory Leak]https://cwe.mitre.org/data/definitions/401.html