Simplifying Struct definition.

Summary:
Since we are reading from a file, we should make sure this struct is packed, just in case we change it down the line and the compiler decides it might want to introduce padding, we're now protected against that.

There was also a discussion about the fact that people might use `ptr += sizeof(BundleHeader)` as an idiom in their code, which would currently be incorrect, if padding was introduced at the end of the file. Actually, it remains incorrect to do that now, because a RAM bundle header is a different size to a BC Bundle header. If people are properly testing their code, they should spot this pretty quickly, because it will always be an incorrect thing to do with a RAM bundle, so this isn't as bad as previously thought: where the code only succeeds when the compiler deigns to not pad the struct at the end.

This diff also cleans up how headers are initialised. `BundleHeader` has a constructor that explicitly zero-initialises it so we can rely on the default initializer to do the right thing now.

Reviewed By: mhorowitz

Differential Revision: D4572032

fbshipit-source-id: 7dc50cfa9438dfdfb9f842dc39d8f15334813c63
This commit is contained in:
Ashok Menon 2017-02-20 04:28:32 -08:00 committed by Facebook Github Bot
parent c02c78a681
commit 1635c02e92
7 changed files with 18 additions and 20 deletions

View File

@ -114,7 +114,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
return nil;
}
facebook::react::BundleHeader header{};
facebook::react::BundleHeader header;
size_t readResult = fread(&header, sizeof(header), 1, bundle);
fclose(bundle);
if (readResult != 1) {
@ -151,11 +151,11 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
}
return nil;
}
else if ((uint32_t)runtimeBCVersion != header.BCVersion) {
else if ((uint32_t)runtimeBCVersion != header.version) {
if (error) {
NSString *errDesc =
[NSString stringWithFormat:@"BC Version Mismatch. Expect: %d, Actual: %u",
runtimeBCVersion, header.BCVersion];
runtimeBCVersion, header.version];
*error = [NSError errorWithDomain:RCTJavaScriptLoaderErrorDomain
code:RCTJavaScriptLoaderErrorBCVersion

View File

@ -87,7 +87,7 @@ static JSValueRef nativePerformanceNow(
}
static bool isRAMBundle(NSData *script) {
BundleHeader header{};
BundleHeader header;
[script getBytes:&header length:sizeof(header)];
return parseTypeFromHeader(header) == ScriptTag::RAMBundle;
}

View File

@ -706,7 +706,7 @@ static TaggedScript loadTaggedScript(NSData *script,
{
RCT_PROFILE_BEGIN_EVENT(0, @"executeApplicationScript / prepare bundle", nil);
facebook::react::BundleHeader header{};
facebook::react::BundleHeader header;
[script getBytes:&header length:sizeof(header)];
facebook::react::ScriptTag tag = facebook::react::parseTypeFromHeader(header);

View File

@ -194,7 +194,7 @@ bool CatalystInstanceImpl::isIndexedRAMBundle(const char *sourcePath) {
if (!bundle_stream) {
return false;
}
BundleHeader header{};
BundleHeader header;
bundle_stream.read(reinterpret_cast<char *>(&header), sizeof(header));
bundle_stream.close();
return parseTypeFromHeader(header) == ScriptTag::RAMBundle;

View File

@ -7,19 +7,19 @@ namespace facebook {
namespace react {
static uint32_t constexpr RAMBundleMagicNumber = 0xFB0BD1E5;
static uint64_t constexpr BCBundleMagicNumber = 0xFF4865726D657300;
static uint32_t constexpr BCBundleMagicNumber = 0x6D657300;
ScriptTag parseTypeFromHeader(const BundleHeader& header) {
if (littleEndianToHost(header.RAMMagic) == RAMBundleMagicNumber) {
switch (littleEndianToHost(header.magic)) {
case RAMBundleMagicNumber:
return ScriptTag::RAMBundle;
}
if (littleEndianToHost(header.BCMagic) == BCBundleMagicNumber) {
case BCBundleMagicNumber:
return ScriptTag::BCBundle;
}
default:
return ScriptTag::String;
}
}
const char *stringForScriptTag(const ScriptTag& tag) {
switch (tag) {

View File

@ -27,16 +27,14 @@ enum struct ScriptTag {
* 4 bytes, for BC bundles this is 12 bytes. This structure holds the first 12
* bytes from a bundle in a way that gives access to that information.
*/
union BundleHeader {
struct __attribute__((packed)) BundleHeader {
BundleHeader() {
std::memset(this, 0, sizeof(BundleHeader));
}
uint32_t RAMMagic;
struct {
uint64_t BCMagic;
uint32_t BCVersion;
};
uint32_t magic;
uint32_t reserved_;
uint32_t version;
};
/**

View File

@ -386,7 +386,7 @@ void JSCExecutor::loadApplicationScript(std::unique_ptr<const JSBigString> scrip
}
}
#elif defined(__APPLE__)
BundleHeader header{};
BundleHeader header;
memcpy(&header, script->c_str(), std::min(script->size(), sizeof(BundleHeader)));
auto scriptTag = parseTypeFromHeader(header);