You're Invited:Meet the Socket Team at BlackHat and DEF CON in Las Vegas, Aug 4-6.RSVP
Socket
Book a DemoInstallSign in
Socket

binary-version-reader

Package Overview
Dependencies
Maintainers
4
Versions
39
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

binary-version-reader - npm Package Compare versions

Comparing version

to
2.2.1

121

lib/moduleEncoding.js

@@ -88,3 +88,14 @@ const { Flags: ModuleFlags, MODULE_PREFIX_SIZE, MIN_MODULE_SUFFIX_SIZE, MAX_MODULE_SUFFIX_SIZE, ModuleInfoExtension, ModuleFunction } = require('./ModuleInfo.js');

/**
* An error reported when assets are over the platform-specific limits
*/
class AssetLimitError extends Error {
constructor(details, ...args) {
super(...args);
this.name = this.constructor.name;
this.details = details;
}
}
// Size of the `compressed_module_header` structure in Device OS

@@ -798,2 +809,8 @@ const COMPRESSED_MODULE_HEADER_SIZE = 8;

if (moduleInfo && moduleInfo.maxSize) {
if (buffer.length > moduleInfo.maxSize) {
throw new AssetLimitError({}, 'Resulting module exceeds platform size limits');
}
}
updateModulePrefix(buffer, prefix);

@@ -889,2 +906,91 @@ updateModuleSuffix(buffer, suffix);

/**
* Validate asset limits
*
* @param {Buffer|string} application Application binary buffer/path
* @param {Array.<object>|Array.<string>} assets Asset data or paths
* @returns {object}
*/
async function validateAssetLimits(application, assets) {
let app = {};
if (typeof application === 'string') {
app.name = path.basename(application);
app.data = await fsAsync.readFile(application);
} else if (application.data && application.name) {
app = application;
} else {
app = {
data: application,
name: 'application.bin'
};
}
const parser = new HalModuleParser();
const { prefixInfo: prefix } = await parser.parsePrefix({ fileBuffer: app.data });
prefix.moduleStartAddy = sanitizeAddress(prefix.moduleStartAddy);
prefix.moduleEndAddy = sanitizeAddress(prefix.moduleEndAddy);
const p = platformsById.get(prefix.platformID);
if (!p) {
throw new RangeError(`Unknown platform ID: ${prefix.platformID}`);
}
if (!p.assets) {
throw new RangeError('This platform does not support assets');
}
const storageLimit = p.assets.blockSize * (p.assets.storageTotalBlocks - p.assets.reservedBlocks);
const errors = [];
const processedAssets = [];
let totalSize = 0;
if (assets) {
for (let asset of assets) {
if (typeof asset === 'string') {
const data = await fsAsync.readFile(asset);
asset = {
data: data,
name: path.basename(asset)
};
}
const assetModule = await createAssetModule(asset.data, asset.name);
const storageSize = p.assets.assetOverhead + Math.ceil((assetModule.length / (p.assets.blockSize - p.assets.assetPerBlockOverhead))) * p.assets.blockSize;
totalSize += storageSize;
processedAssets.push({
moduleSize: assetModule.length,
storageSize,
name: asset.name,
originalSize: asset.data.length
});
}
}
const details = {
maxSingleAssetSize: p.assets.maxSingleAssetSize,
maxTotalAssetSize: storageLimit,
assets: processedAssets,
totalAssetSize: totalSize,
errors
};
for (let asset of processedAssets) {
if (asset.moduleSize > p.assets.maxSingleAssetSize) {
errors.push(new AssetLimitError(details, `Asset ${asset.name} exceeds maximum single asset size limit by ${asset.moduleSize - details.maxSingleAssetSize} bytes`));
}
}
if (totalSize > storageLimit) {
errors.push(new AssetLimitError(details, `Total size of assets exceeds platform limits by ${totalSize - storageLimit} bytes`));
}
if (errors.length > 0) {
// Throw first one, additional can be accessed in err.details.errors
throw errors[0];
}
return details;
}
/**
* Create application and asset bundle

@@ -927,3 +1033,12 @@ *

if (processedAssets.length > 0) {
updated = await updateModuleAssetDependencies(app.data, processedAssets);
const details = await validateAssetLimits(app, processedAssets);
try {
updated = await updateModuleAssetDependencies(app.data, processedAssets);
} catch (err) {
if (err instanceof AssetLimitError) {
err.details = details;
err.details.errors.push(err);
throw err;
}
}
} else {

@@ -1268,3 +1383,5 @@ updated = app.data;

sanitizeAddress,
isAssetValid
isAssetValid,
validateAssetLimits,
AssetLimitError
};

7

package.json
{
"name": "binary-version-reader",
"version": "2.2.0",
"version": "2.2.1",
"main": "main.js",

@@ -19,8 +19,9 @@ "license": "Apache-2.0",

"peerDependencies": {
"@particle/device-constants": "^3.1.11"
"@particle/device-constants": "^3.2.0"
},
"devDependencies": {
"@particle/device-constants": "^3.1.11",
"@particle/device-constants": "^3.2.0",
"buffer-offset": "^0.1.2",
"chai": "^4.0.0",
"chai-as-promised": "^7.1.1",
"chai-exclude": "^2.1.0",

@@ -27,0 +28,0 @@ "coveralls": "^3.0.7",

@@ -1,12 +0,11 @@

The Particle Binary Version Reader!
=====
# The Particle Binary Version Reader!
If you're building firmware on the Particle Platform, you might be curious to see the metadata stored in your firmware! This module will read any metadata stored in the various modules (bootloader, system, user), and help you understand any dependencies.
[![Build Status](https://travis-ci.org/particle-iot/binary-version-reader.svg?branch=master)](https://travis-ci.org/particle-iot/binary-version-reader)
[![Build Status](https://github.com/particle-iot/binary-version-reader/actions/workflows/ci.yaml/badge.svg)](https://github.com/particle-iot/binary-version-reader/actions)
Usage
===
## Usage
```js

@@ -26,4 +25,3 @@ const Reader = require('binary-version-reader').HalModuleParser;

Example output
===
## Example output

@@ -69,4 +67,4 @@ ```json

```
const firmwareTestHelper = require('binary-version-reader');
const binary = firmwareTestHelper.createFirmwareBinary({ productId: 123, productVersion: 6, platformId: 10, depModuleVersion: 1210 });
const { firmwareTestHelper, ModuleInfo } = require('binary-version-reader');
const binary = firmwareTestHelper.createFirmwareBinary({ productId: 123, productVersion: 6, platformId: 10, deps: [ { func: ModuleInfo.FunctionType.SYSTEM_PART, index: 1, version: 1210 } ] });
```

@@ -73,0 +71,0 @@

@@ -16,3 +16,4 @@ const {

sanitizeAddress,
isAssetValid
isAssetValid,
AssetLimitError
} = require('../../lib/moduleEncoding');

@@ -31,2 +32,5 @@

const chaiAsPromised = require('chai-as-promised');
chai.use(chaiAsPromised);
const crypto = require('crypto');

@@ -703,2 +707,31 @@ const path = require('path');

});
it('throws an error when application binary with added asset dependencies exceeds platform size limit', async () => {
const application = fs.readFileSync(path.join(TEST_BINARIES_PATH, 'tracker-max-size@5.5.0-rc.1.bin'));
const assets = [];
for (let i = 0; i < 100; i++) {
assets.push({
data: genRandomBuffer(1),
name: genRandomBuffer(127).toString('hex')
});
}
return expect(createApplicationAndAssetBundle(application, assets)).to.be.rejectedWith(AssetLimitError, 'Resulting module exceeds platform size limits');
});
it('throws an error when asset exceeds maximum single asset size limit on Tracker platform', async () => {
const application = fs.readFileSync(path.join(TEST_BINARIES_PATH, 'tracker-tinker@5.3.1.bin'));
return expect(createApplicationAndAssetBundle(application, [{ data: genRandomBuffer(10 * 1024 * 1024), name: 'test.bin' }])).to.be.rejectedWith(AssetLimitError, /maximum single asset size limit/);
});
it('throws an error when assets exceed total maximum size of assets on Tracker platform', async () => {
const application = fs.readFileSync(path.join(TEST_BINARIES_PATH, 'tracker-tinker@5.3.1.bin'));
const assets = [];
for (let i = 0; i < 10; i++) {
assets.push({
data: genRandomBuffer(400 * 1024),
name: genRandomBuffer(127).toString('hex')
});
}
return expect(createApplicationAndAssetBundle(application, assets)).to.be.rejectedWith(AssetLimitError, /Total size of assets exceeds/);
});
});

@@ -705,0 +738,0 @@