Comments (4)
Or, if you prefer the code in text:
(I extracted rapid yaml as a single header to a file rapidyaml.h
):
main.cpp
#include "yamlreader.h"
int main()
{
YamlReader reader("./test.yaml");
reader.printTree();
return 0;
}
yamlreader.h
#define RYML_SINGLE_HDR_DEFINE_NOW
#include "rapidyaml.h"
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
class YamlReader
{
using Tree = c4::yml::Tree;
public: // attributes
std::shared_ptr<Tree> m_Tree = nullptr;
public: // methods
YamlReader(const std::string&);
void printTree();
};
YamlReader::YamlReader(const std::string &filename)
{
std::string buffer;
{
std::ifstream file(filename);
if (file) {
std::stringstream ssbuf;
ssbuf << file.rdbuf();
buffer = ssbuf.str();
}
}
if (!buffer.empty()) {
m_Tree = std::make_shared<Tree>(ryml::parse_in_place(ryml::to_substr(buffer)));
// Resolve anchors and references
m_Tree->resolve();
}
}
void YamlReader::printTree()
{
if (!m_Tree)
return;
std::cerr << "\n********************" << std::endl;
std::string key;
for (auto child : m_Tree->rootref()) {
std::cerr << " - entry: " << child << std::endl;
if (child.has_key()) {
child >> ryml::key(key);
}
std::cerr << " - key: " << key << std::endl << std::endl;
}
std::cerr << "********************" << "\n" << std::endl;
}
test.yaml
first-definition:
type: node
x: 5
second-definition:
type: node
x: 10
main_2.cpp
#define RYML_SINGLE_HDR_DEFINE_NOW
#include "rapidyaml.h"
#include <iostream>
#include <fstream>
#include <memory>
#include <string>
#include <sstream>
using Tree = c4::yml::Tree;
using namespace std;
void printOut(std::shared_ptr<Tree> tree)
{
if (tree) {
std::string key;
std::cerr << "\n********************" << std::endl;
for (auto child : tree->rootref()) {
if (child.has_key()) {
child >> ryml::key(key);
std::cerr << " - key: " << key << std::endl << std::endl;
}
std::cerr << " - entry: " << child<< std::endl;
}
std::cerr << "********************" << "\n" << std::endl;
}
}
int main()
{
std::string buffer;
{
std::ifstream file("./test.yaml");
if (file) {
std::stringstream ssbuf;
ssbuf << file.rdbuf();
buffer = ssbuf.str();
}
}
if (!buffer.empty()) {
std::shared_ptr<Tree> tree = std::make_shared<Tree>(ryml::parse_in_place(ryml::to_substr(buffer)));
tree->resolve();
printOut(tree);
}
return 0;
}
from rapidyaml.
There's a read after free in your code:
YamlReader::YamlReader(const std::string &filename)
{
std::string buffer; // BANG! (1)
{
std::ifstream file(filename);
if (file) {
std::stringstream ssbuf;
ssbuf << file.rdbuf();
buffer = ssbuf.str();
}
}
if (!buffer.empty()) {
// BANG! (2)
m_Tree = std::make_shared<Tree>(ryml::parse_in_place(ryml::to_substr(buffer)));
// Resolve anchors and references
m_Tree->resolve();
}
// BANG! (3)
}
You are reading the file into a function-local variable buffer
in (1), and you are using parse_in_place()
to parse the contents in (2). This will populate the tree with pointers to buffer
. But then buffer
goes out of scope and is freed in (3).
So after this function returns, the tree is pointing into freed memory. Hence your read-after-free.
There are two ways to fix your code:
- use
parse_in_arena()
which will copy the contents ofbuffer
into the tree's arena before parsing the arena in place - OR preferably, save the copy and just make
buffer
a member of your class, preventing it from being freed.
Really, this is amply explained in the docs: ryml merely holds views to the YAML buffer. It is up to you -- meaning that it is both your power and your responsibility -- to decide where to store it, and then ensure the lifetimes of the buffer and tree match.
from rapidyaml.
There is yet another problem with your class: the tree will not be initialized when the buffer is empty. I suggest removing the if(!buffer.empty())
branch.
from rapidyaml.
I had somehow missed the parse_in_place
subtility. That makes sense. Thank you.
from rapidyaml.
Related Issues (20)
- Is scientific notation number supported? HOT 1
- Support for Python 3.12
- rapidyaml assigning out-of-bound id values to new nodes
- How to create a node where key is a dynamic string? HOT 2
- Request: Add more context to error traces HOT 3
- Tree::resolve() leaves some references in place in certain cases HOT 1
- Publish support for more platforms to Conan Central HOT 1
- How to get the correct col for a multiline string
- [Feature Request] Add an option to support customize installation HOT 2
- Rapidyaml calls abort(3) on random input HOT 3
- Question: filter utility use case HOT 3
- Error message 'closing ] not found' does not use _c4err macro
- An incomprehensible behavior occurred while using the for loop HOT 2
- Empty string instead of null serialized for nullptr HOT 1
- Meaning of .val()==nullptr and .has_val() HOT 2
- Namespace conflict with windows.h HOT 1
- Decimal precision truncated when serialize/deserialize std::vector<double> container HOT 2
- [Request] Make new release HOT 3
- [Bug] Text data with commas is incorrectly split HOT 4
- Serialize std::filesystem::path error HOT 16
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from rapidyaml.