-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Replace yaml-cpp with libyaml #535
Conversation
… all winget-pkgs files validate
src/YamlCppLib/readme.md
Outdated
|
||
#### Steps used to create the VS project files. | ||
|
||
1. VS Create project from existing code wizard to pint to yaml-cpp directory. Use static library template. | ||
1. VS Create project from existing code wizard to point to libyaml directory. Use static library template. | ||
2. Removed code not needed by AppInstallerClient project. Basically keeping only files under src and include. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AppInstallerClient [](start = 30, length = 18)
nit: forgot to update to WinGet here and below #Resolved
<ItemGroup> | ||
<Content Include="TestData\**"> | ||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> | ||
</Content> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<None Remove="TestData\Manifests\TestWarningManifest.yaml" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[](start = 3, length = 62)
looks like not needed #Resolved
@@ -0,0 +1,12 @@ | |||
Id: TestInvalid.Manifest | |||
Name: TestInvalidManifest |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Invalid [](start = 10, length = 7)
maybe Warning here #Resolved
} | ||
|
||
bool IsDefined() const { return m_type != Type::Invalid; } | ||
bool IsNull() const { return m_type == Type::Invalid || m_type == Type::None || (m_type == Type::Scalar && m_scalar.empty()); } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
m_type == Type::Invalid [](start = 37, length = 23)
should we allow Invalid as null? #ByDesign
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was to match the behavior of yaml-cpp with respect to what we generate from libyaml.
In reply to: 468973641 [](ancestors = 468973641)
@@ -41,6 +41,17 @@ | |||
#define APPINSTALLER_CLI_ERROR_EXPERIMENTAL_FEATURE_DISABLED ((HRESULT)0x8A15001D) | |||
#define APPINSTALLER_CLI_ERROR_MSSTORE_INSTALL_FAILED ((HRESULT)0x8A15001E) | |||
#define APPINSTALLER_CLI_ERROR_COMPLETE_INPUT_BAD ((HRESULT)0x8A15001F) | |||
#define APPINSTALLER_CLI_ERROR_YAML_INIT_FAILED ((HRESULT)0x8A150020) | |||
#define APPINSTALLER_CLI_ERROR_INVALID_MAPPING_KEY ((HRESULT)0x8A150021) | |||
#define APPINSTALLER_CLI_ERROR_DUPLICATE_MAPPING_KEY ((HRESULT)0x8A150022) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe YAML for these 2 as well? #Resolved
// Detects empty files with a better error. | ||
if (!rootNode.IsMap()) | ||
{ | ||
THROW_EXCEPTION_MSG(ManifestException(APPINSTALLER_CLI_ERROR_INVALID_MANIFEST), "The manifest does not contain a valid root."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
APPINSTALLER_CLI_ERROR_INVALID_MANIFEST [](start = 50, length = 39)
There's an existing error code for manifest failure APPINSTALLER_CLI_ERROR_MANIFEST_FAILED, should we merge the 2? #ByDesign
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is the more generic parsing error. It is rarely bad to have a more specific error.
In reply to: 468974896 [](ancestors = 468974896)
@@ -12,7 +12,8 @@ | |||
|
|||
#include "TraceLogging.h" | |||
|
|||
#include <yaml-cpp/yaml.h> | |||
#define YAML_DECLARE_STATIC |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
YAML_DECLARE_STATIC [](start = 8, length = 19)
Is this intended here? #ByDesign
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. I could put it in the project, but I don't see the value. Here it is tied to the header it actually is related to.
In reply to: 468976197 [](ancestors = 468976197)
{ | ||
if (init) | ||
{ | ||
if (!yaml_document_initialize(&m_document, NULL, NULL, NULL, 1, 1)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NULL, NULL, NULL, 1, 1 [](start = 55, length = 22)
maybe a comment on what these parameters mean? #Resolved
std::ostringstream out; | ||
OutputExceptionHeader(out, type); | ||
|
||
out << (problem ? problem : "Unexplained error"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Unexplained error" [](start = 36, length = 19)
nit; I feel "Unknown error" is less confusing for me #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After a second thought, "unexplained" seems better fit
In reply to: 468993477 [](ancestors = 468993477)
src/AppInstallerCommonCore/Yaml.cpp
Outdated
THROW_HR_IF(APPINSTALLER_CLI_ERROR_YAML_INVALID_OPERATION, m_type != type); | ||
} | ||
|
||
void Node::Require(Type type1, Type type2) const |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Require [](start = 15, length = 7)
I think this is never used or not even possible? #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was used previously, but I had to change the code. It is possible, it is simply !(type1 || type2).
In reply to: 468995615 [](ancestors = 468995615)
src/AppInstallerCommonCore/Yaml.cpp
Outdated
|
||
bool Node::as_dispatch(bool*) const | ||
{ | ||
if (m_scalar == "true") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
m_scalar [](start = 12, length = 8)
I think yaml spec recommends case insensitive #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I looked at it I didn't see it called out. I can do case insensitive though.
In reply to: 468996962 [](ancestors = 468996962)
Emitter::Emitter(Emitter&&) = default; | ||
Emitter& Emitter::operator=(Emitter&&) = default; | ||
|
||
Emitter::~Emitter() = default; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
curious why not put these in the header?
#ByDesign
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm using pImpl idioms here to remove the need for the libyaml header to be included in all of the consumers of our Yaml.h. In order to do that, the std::unique_ptr's destructor (and anything that requires the complete type) must only be referenced within the cpp. So these functions are actually "implemented" here, rather than allowing them to be written out in every other TU and be folded by the compiler (or however they actually implement inline header functions).
In reply to: 468997684 [](ancestors = 468997684)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also fixes #312 , see below for details.
Change
Due to certain bugs in yaml-cpp, it has not had significant fuzzing applied. Even if those bugs were fixed, it is unknown how many more might exist behind it. In order to avoid chasing those bugs, we are switching to a YAML parser that does have significant fuzz testing coverage, libyaml.
In addition to the use of libyaml, a C++ wrapper is written to create a near identical surface area for use by the existing manifest validation. It also includes encoding detection to enable support for ANSI (assumed Windows-1252, which wasn't supported by yaml-cpp), UTF-8 (with and without BOM), UTF-16 LE/BE (both with and without BOM).
Finally, the
validate
command now returns a non-zero value when there are issues. If there is a failure during validation, the value returned is0x8A150029
. If there are only warnings, the value returned is0x8A150028
.Validation
In addition to the regression testing, new tests are added for the
validate
command and its return values. New tests are also added for the various different text encoding types.I also used scripts to run
validate
andshow
against every manifest in the winget-pkgs repo. They all validate successfully, and the only difference in show presentation that I found was a single file that contained an ANSI © character which was being translated to unknown in the older parser, but is working properly with the new code.Microsoft Reviewers: Open in CodeFlow