Skip to content

Fix encoding/decoding of base-256 numbers - #215

Merged
isaacs merged 2 commits into
isaacs:masterfrom
justfalter:fix-base-256
Jun 1, 2019
Merged

Fix encoding/decoding of base-256 numbers#215
isaacs merged 2 commits into
isaacs:masterfrom
justfalter:fix-base-256

Conversation

@justfalter

@justfalterjustfalter commented May 30, 2019

Copy link
Copy Markdown
Contributor

This PR fixes issues I've identified with the handling of base-256 encoded numbers within node-tar (see #188). The issues would generally present themselves when attempting to extract a gnu-formatted tar entry for a file greater than 8gb in size.

  • The last byte of the buffer was incorrectly being ignored when encoding/decoding.
  • Javascript can only have safe integer precision for numbers between -9007199254740991 and 9007199254740991. Any numbers outside these bounds will see the lowest-order bits rounded off. For example, 9007199254749999 will be rounded to 9007199254750000.
  • I've modified large-integer.jsparse and encode functions to throw TypeError exceptions if they encounter a number that will not be precisely represented as a javascript integer, or if the buffer being decoded does not appear to be a base-256 encoded number (must start with 80 or ff).

- Encoding/decoding of base-256 numbers failed to failed to handle last
byte in buffer. Handling was previously broken.
- Take javascript's MAX_SAFE_INTEGER / MIN_SAFE_INTEGER into account
when encoding/decoding. Namely, if the numbers cannot accurately be
represented in javascript with integer-precision, a TypeError will be
thrown.
- Throw a TypeError if the parser is passed an buffer that does not
appear to be base-256 encoded. (must start with 0x80 or 0xff)
Comment threadlib/large-numbers.js Outdated
@isaacs
isaacs merged commit 9a44de7 into isaacs:masterJun 1, 2019
@isaacs

Copy link
Copy Markdown
Owner

I see what happened here.

To encode files over 8gb, bsdtar drops the trailing 0x20, and uses that as a part of the octal-in-ascii number. This is an ambiguous part of the spec (such as it is), which gnutar interprets differently. Thankfully, bsdtar also prepends a PAX extended file attributes entry, which gnutar interprets properly. So, for example, a 10gb file would fill those 12 bytes with '120000000000', no terminator. Gnutar misinterprets this as 0o12000000000 (a mere 1.25 Gb), but that's overridden by the PAX header.

I'm not sure what bsdtar would write in that block if the file size couldn't fit in 12 octal digits, but I'm also not eager to create a 64 gb file on my laptop to find out.

@isaacs

Copy link
Copy Markdown
Owner

Actually I did get curious and checked. Bsdtar does the same thing as gnutar, but only when the file is 64gb or greater.

In short, this patch is good, it's landed, and published to latest. Thank you for digging in and fixing this. The reason it escaped my notice for so long is frankly that pax headers are so much more straightforward and make this type of bug irrelevant in so many cases.

The checks for Number.MAX_SAFE_INTEGER made me chuckle. I thought for a second that throwing a new error should be semver major bump, but if people are using this library to pack and unpack tarballs with 8 petabyte files in them, then the world is definitely in trouble.

@justfalter

Copy link
Copy Markdown
ContributorAuthor

Thanks for taking the time to go over this, @isaacs. I’ve got something upstream from my project that is explicitly producing gnu-formatted tarballs, for some reason.

Honestly, the only reason I even thought to do the min/max int checks were because you had tests that would have violated those checks. 8 petabyte files are pretty unlikely, but I wondered if there weren’t other numbers that might be encoded (uid, his, etc) that might someday exceed max int. I dug a bit into libarchive, and they have similar checks, there, as well.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@justfalter@isaacs@sdball
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all \x3Cpre>\x3Ccode> blocks (function() { function addCopyButtons() { document.querySelectorAll('pre code').forEach(function(codeBlock) { if (codeBlock.parentElement.hasAttribute('data-copy-added')) return; codeBlock.parentElement.setAttribute('data-copy-added', 'true'); var btn = document.createElement('button'); btn.textContent = 'Copy'; btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;'; btn.onmouseover = function() { this.style.opacity = '1'; }; btn.onmouseout = function() { this.style.opacity = '0.7'; }; btn.onclick = function() { navigator.clipboard.writeText(codeBlock.textContent).then(function() { btn.textContent = 'Copied!'; setTimeout(function() { btn.textContent = 'Copy'; }, 1500); }); }; codeBlock.parentElement.style.position = 'relative'; codeBlock.parentElement.appendChild(btn); }); } addCopyButtons(); // Re-run on dynamic content var observer = new MutationObserver(addCopyButtons); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); } })(); (function(){ try { var __m = "github.com"; var __re = new RegExp('^' + "github\\.com" + ' Fix encoding/decoding of base-256 numbers by justfalter · Pull Request #215 · isaacs/node-tar · GitHub
Skip to content

Fix encoding/decoding of base-256 numbers - #215

Merged
isaacs merged 2 commits into
isaacs:masterfrom
justfalter:fix-base-256
Jun 1, 2019
Merged

Fix encoding/decoding of base-256 numbers#215
isaacs merged 2 commits into
isaacs:masterfrom
justfalter:fix-base-256

Conversation

@justfalter

@justfalterjustfalter commented May 30, 2019

Copy link
Copy Markdown
Contributor

This PR fixes issues I've identified with the handling of base-256 encoded numbers within node-tar (see #188). The issues would generally present themselves when attempting to extract a gnu-formatted tar entry for a file greater than 8gb in size.

  • The last byte of the buffer was incorrectly being ignored when encoding/decoding.
  • Javascript can only have safe integer precision for numbers between -9007199254740991 and 9007199254740991. Any numbers outside these bounds will see the lowest-order bits rounded off. For example, 9007199254749999 will be rounded to 9007199254750000.
  • I've modified large-integer.jsparse and encode functions to throw TypeError exceptions if they encounter a number that will not be precisely represented as a javascript integer, or if the buffer being decoded does not appear to be a base-256 encoded number (must start with 80 or ff).

- Encoding/decoding of base-256 numbers failed to failed to handle last
byte in buffer. Handling was previously broken.
- Take javascript's MAX_SAFE_INTEGER / MIN_SAFE_INTEGER into account
when encoding/decoding. Namely, if the numbers cannot accurately be
represented in javascript with integer-precision, a TypeError will be
thrown.
- Throw a TypeError if the parser is passed an buffer that does not
appear to be base-256 encoded. (must start with 0x80 or 0xff)
Comment threadlib/large-numbers.js Outdated
@isaacs
isaacs merged commit 9a44de7 into isaacs:masterJun 1, 2019
@isaacs

Copy link
Copy Markdown
Owner

I see what happened here.

To encode files over 8gb, bsdtar drops the trailing 0x20, and uses that as a part of the octal-in-ascii number. This is an ambiguous part of the spec (such as it is), which gnutar interprets differently. Thankfully, bsdtar also prepends a PAX extended file attributes entry, which gnutar interprets properly. So, for example, a 10gb file would fill those 12 bytes with '120000000000', no terminator. Gnutar misinterprets this as 0o12000000000 (a mere 1.25 Gb), but that's overridden by the PAX header.

I'm not sure what bsdtar would write in that block if the file size couldn't fit in 12 octal digits, but I'm also not eager to create a 64 gb file on my laptop to find out.

@isaacs

Copy link
Copy Markdown
Owner

Actually I did get curious and checked. Bsdtar does the same thing as gnutar, but only when the file is 64gb or greater.

In short, this patch is good, it's landed, and published to latest. Thank you for digging in and fixing this. The reason it escaped my notice for so long is frankly that pax headers are so much more straightforward and make this type of bug irrelevant in so many cases.

The checks for Number.MAX_SAFE_INTEGER made me chuckle. I thought for a second that throwing a new error should be semver major bump, but if people are using this library to pack and unpack tarballs with 8 petabyte files in them, then the world is definitely in trouble.

@justfalter

Copy link
Copy Markdown
ContributorAuthor

Thanks for taking the time to go over this, @isaacs. I’ve got something upstream from my project that is explicitly producing gnu-formatted tarballs, for some reason.

Honestly, the only reason I even thought to do the min/max int checks were because you had tests that would have violated those checks. 8 petabyte files are pretty unlikely, but I wondered if there weren’t other numbers that might be encoded (uid, his, etc) that might someday exceed max int. I dug a bit into libarchive, and they have similar checks, there, as well.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@justfalter@isaacs@sdball
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Fix encoding/decoding of base-256 numbers by justfalter · Pull Request #215 · isaacs/node-tar · GitHub
Skip to content

Fix encoding/decoding of base-256 numbers - #215

Merged
isaacs merged 2 commits into
isaacs:masterfrom
justfalter:fix-base-256
Jun 1, 2019
Merged

Fix encoding/decoding of base-256 numbers#215
isaacs merged 2 commits into
isaacs:masterfrom
justfalter:fix-base-256

Conversation

@justfalter

@justfalterjustfalter commented May 30, 2019

Copy link
Copy Markdown
Contributor

This PR fixes issues I've identified with the handling of base-256 encoded numbers within node-tar (see #188). The issues would generally present themselves when attempting to extract a gnu-formatted tar entry for a file greater than 8gb in size.

  • The last byte of the buffer was incorrectly being ignored when encoding/decoding.
  • Javascript can only have safe integer precision for numbers between -9007199254740991 and 9007199254740991. Any numbers outside these bounds will see the lowest-order bits rounded off. For example, 9007199254749999 will be rounded to 9007199254750000.
  • I've modified large-integer.jsparse and encode functions to throw TypeError exceptions if they encounter a number that will not be precisely represented as a javascript integer, or if the buffer being decoded does not appear to be a base-256 encoded number (must start with 80 or ff).

- Encoding/decoding of base-256 numbers failed to failed to handle last
byte in buffer. Handling was previously broken.
- Take javascript's MAX_SAFE_INTEGER / MIN_SAFE_INTEGER into account
when encoding/decoding. Namely, if the numbers cannot accurately be
represented in javascript with integer-precision, a TypeError will be
thrown.
- Throw a TypeError if the parser is passed an buffer that does not
appear to be base-256 encoded. (must start with 0x80 or 0xff)
Comment threadlib/large-numbers.js Outdated
@isaacs
isaacs merged commit 9a44de7 into isaacs:masterJun 1, 2019
@isaacs

Copy link
Copy Markdown
Owner

I see what happened here.

To encode files over 8gb, bsdtar drops the trailing 0x20, and uses that as a part of the octal-in-ascii number. This is an ambiguous part of the spec (such as it is), which gnutar interprets differently. Thankfully, bsdtar also prepends a PAX extended file attributes entry, which gnutar interprets properly. So, for example, a 10gb file would fill those 12 bytes with '120000000000', no terminator. Gnutar misinterprets this as 0o12000000000 (a mere 1.25 Gb), but that's overridden by the PAX header.

I'm not sure what bsdtar would write in that block if the file size couldn't fit in 12 octal digits, but I'm also not eager to create a 64 gb file on my laptop to find out.

@isaacs

Copy link
Copy Markdown
Owner

Actually I did get curious and checked. Bsdtar does the same thing as gnutar, but only when the file is 64gb or greater.

In short, this patch is good, it's landed, and published to latest. Thank you for digging in and fixing this. The reason it escaped my notice for so long is frankly that pax headers are so much more straightforward and make this type of bug irrelevant in so many cases.

The checks for Number.MAX_SAFE_INTEGER made me chuckle. I thought for a second that throwing a new error should be semver major bump, but if people are using this library to pack and unpack tarballs with 8 petabyte files in them, then the world is definitely in trouble.

@justfalter

Copy link
Copy Markdown
ContributorAuthor

Thanks for taking the time to go over this, @isaacs. I’ve got something upstream from my project that is explicitly producing gnu-formatted tarballs, for some reason.

Honestly, the only reason I even thought to do the min/max int checks were because you had tests that would have violated those checks. 8 petabyte files are pretty unlikely, but I wondered if there weren’t other numbers that might be encoded (uid, his, etc) that might someday exceed max int. I dug a bit into libarchive, and they have similar checks, there, as well.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@justfalter@isaacs@sdball
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Fix encoding/decoding of base-256 numbers by justfalter · Pull Request #215 · isaacs/node-tar · GitHub
Skip to content

Fix encoding/decoding of base-256 numbers - #215

Merged
isaacs merged 2 commits into
isaacs:masterfrom
justfalter:fix-base-256
Jun 1, 2019
Merged

Fix encoding/decoding of base-256 numbers#215
isaacs merged 2 commits into
isaacs:masterfrom
justfalter:fix-base-256

Conversation

@justfalter

@justfalterjustfalter commented May 30, 2019

Copy link
Copy Markdown
Contributor

This PR fixes issues I've identified with the handling of base-256 encoded numbers within node-tar (see #188). The issues would generally present themselves when attempting to extract a gnu-formatted tar entry for a file greater than 8gb in size.

  • The last byte of the buffer was incorrectly being ignored when encoding/decoding.
  • Javascript can only have safe integer precision for numbers between -9007199254740991 and 9007199254740991. Any numbers outside these bounds will see the lowest-order bits rounded off. For example, 9007199254749999 will be rounded to 9007199254750000.
  • I've modified large-integer.jsparse and encode functions to throw TypeError exceptions if they encounter a number that will not be precisely represented as a javascript integer, or if the buffer being decoded does not appear to be a base-256 encoded number (must start with 80 or ff).

- Encoding/decoding of base-256 numbers failed to failed to handle last
byte in buffer. Handling was previously broken.
- Take javascript's MAX_SAFE_INTEGER / MIN_SAFE_INTEGER into account
when encoding/decoding. Namely, if the numbers cannot accurately be
represented in javascript with integer-precision, a TypeError will be
thrown.
- Throw a TypeError if the parser is passed an buffer that does not
appear to be base-256 encoded. (must start with 0x80 or 0xff)
Comment threadlib/large-numbers.js Outdated
@isaacs
isaacs merged commit 9a44de7 into isaacs:masterJun 1, 2019
@isaacs

Copy link
Copy Markdown
Owner

I see what happened here.

To encode files over 8gb, bsdtar drops the trailing 0x20, and uses that as a part of the octal-in-ascii number. This is an ambiguous part of the spec (such as it is), which gnutar interprets differently. Thankfully, bsdtar also prepends a PAX extended file attributes entry, which gnutar interprets properly. So, for example, a 10gb file would fill those 12 bytes with '120000000000', no terminator. Gnutar misinterprets this as 0o12000000000 (a mere 1.25 Gb), but that's overridden by the PAX header.

I'm not sure what bsdtar would write in that block if the file size couldn't fit in 12 octal digits, but I'm also not eager to create a 64 gb file on my laptop to find out.

@isaacs

Copy link
Copy Markdown
Owner

Actually I did get curious and checked. Bsdtar does the same thing as gnutar, but only when the file is 64gb or greater.

In short, this patch is good, it's landed, and published to latest. Thank you for digging in and fixing this. The reason it escaped my notice for so long is frankly that pax headers are so much more straightforward and make this type of bug irrelevant in so many cases.

The checks for Number.MAX_SAFE_INTEGER made me chuckle. I thought for a second that throwing a new error should be semver major bump, but if people are using this library to pack and unpack tarballs with 8 petabyte files in them, then the world is definitely in trouble.

@justfalter

Copy link
Copy Markdown
ContributorAuthor

Thanks for taking the time to go over this, @isaacs. I’ve got something upstream from my project that is explicitly producing gnu-formatted tarballs, for some reason.

Honestly, the only reason I even thought to do the min/max int checks were because you had tests that would have violated those checks. 8 petabyte files are pretty unlikely, but I wondered if there weren’t other numbers that might be encoded (uid, his, etc) that might someday exceed max int. I dug a bit into libarchive, and they have similar checks, there, as well.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@justfalter@isaacs@sdball
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' Fix encoding/decoding of base-256 numbers by justfalter · Pull Request #215 · isaacs/node-tar · GitHub
Skip to content

Fix encoding/decoding of base-256 numbers - #215

Merged
isaacs merged 2 commits into
isaacs:masterfrom
justfalter:fix-base-256
Jun 1, 2019
Merged

Fix encoding/decoding of base-256 numbers#215
isaacs merged 2 commits into
isaacs:masterfrom
justfalter:fix-base-256

Conversation

@justfalter

@justfalterjustfalter commented May 30, 2019

Copy link
Copy Markdown
Contributor

This PR fixes issues I've identified with the handling of base-256 encoded numbers within node-tar (see #188). The issues would generally present themselves when attempting to extract a gnu-formatted tar entry for a file greater than 8gb in size.

  • The last byte of the buffer was incorrectly being ignored when encoding/decoding.
  • Javascript can only have safe integer precision for numbers between -9007199254740991 and 9007199254740991. Any numbers outside these bounds will see the lowest-order bits rounded off. For example, 9007199254749999 will be rounded to 9007199254750000.
  • I've modified large-integer.jsparse and encode functions to throw TypeError exceptions if they encounter a number that will not be precisely represented as a javascript integer, or if the buffer being decoded does not appear to be a base-256 encoded number (must start with 80 or ff).

- Encoding/decoding of base-256 numbers failed to failed to handle last
byte in buffer. Handling was previously broken.
- Take javascript's MAX_SAFE_INTEGER / MIN_SAFE_INTEGER into account
when encoding/decoding. Namely, if the numbers cannot accurately be
represented in javascript with integer-precision, a TypeError will be
thrown.
- Throw a TypeError if the parser is passed an buffer that does not
appear to be base-256 encoded. (must start with 0x80 or 0xff)
Comment threadlib/large-numbers.js Outdated
@isaacs
isaacs merged commit 9a44de7 into isaacs:masterJun 1, 2019
@isaacs

Copy link
Copy Markdown
Owner

I see what happened here.

To encode files over 8gb, bsdtar drops the trailing 0x20, and uses that as a part of the octal-in-ascii number. This is an ambiguous part of the spec (such as it is), which gnutar interprets differently. Thankfully, bsdtar also prepends a PAX extended file attributes entry, which gnutar interprets properly. So, for example, a 10gb file would fill those 12 bytes with '120000000000', no terminator. Gnutar misinterprets this as 0o12000000000 (a mere 1.25 Gb), but that's overridden by the PAX header.

I'm not sure what bsdtar would write in that block if the file size couldn't fit in 12 octal digits, but I'm also not eager to create a 64 gb file on my laptop to find out.

@isaacs

Copy link
Copy Markdown
Owner

Actually I did get curious and checked. Bsdtar does the same thing as gnutar, but only when the file is 64gb or greater.

In short, this patch is good, it's landed, and published to latest. Thank you for digging in and fixing this. The reason it escaped my notice for so long is frankly that pax headers are so much more straightforward and make this type of bug irrelevant in so many cases.

The checks for Number.MAX_SAFE_INTEGER made me chuckle. I thought for a second that throwing a new error should be semver major bump, but if people are using this library to pack and unpack tarballs with 8 petabyte files in them, then the world is definitely in trouble.

@justfalter

Copy link
Copy Markdown
ContributorAuthor

Thanks for taking the time to go over this, @isaacs. I’ve got something upstream from my project that is explicitly producing gnu-formatted tarballs, for some reason.

Honestly, the only reason I even thought to do the min/max int checks were because you had tests that would have violated those checks. 8 petabyte files are pretty unlikely, but I wondered if there weren’t other numbers that might be encoded (uid, his, etc) that might someday exceed max int. I dug a bit into libarchive, and they have similar checks, there, as well.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@justfalter@isaacs@sdball
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Fix encoding/decoding of base-256 numbers by justfalter · Pull Request #215 · isaacs/node-tar · GitHub
Skip to content

Fix encoding/decoding of base-256 numbers - #215

Merged
isaacs merged 2 commits into
isaacs:masterfrom
justfalter:fix-base-256
Jun 1, 2019
Merged

Fix encoding/decoding of base-256 numbers#215
isaacs merged 2 commits into
isaacs:masterfrom
justfalter:fix-base-256

Conversation

@justfalter

@justfalterjustfalter commented May 30, 2019

Copy link
Copy Markdown
Contributor

This PR fixes issues I've identified with the handling of base-256 encoded numbers within node-tar (see #188). The issues would generally present themselves when attempting to extract a gnu-formatted tar entry for a file greater than 8gb in size.

  • The last byte of the buffer was incorrectly being ignored when encoding/decoding.
  • Javascript can only have safe integer precision for numbers between -9007199254740991 and 9007199254740991. Any numbers outside these bounds will see the lowest-order bits rounded off. For example, 9007199254749999 will be rounded to 9007199254750000.
  • I've modified large-integer.jsparse and encode functions to throw TypeError exceptions if they encounter a number that will not be precisely represented as a javascript integer, or if the buffer being decoded does not appear to be a base-256 encoded number (must start with 80 or ff).

- Encoding/decoding of base-256 numbers failed to failed to handle last
byte in buffer. Handling was previously broken.
- Take javascript's MAX_SAFE_INTEGER / MIN_SAFE_INTEGER into account
when encoding/decoding. Namely, if the numbers cannot accurately be
represented in javascript with integer-precision, a TypeError will be
thrown.
- Throw a TypeError if the parser is passed an buffer that does not
appear to be base-256 encoded. (must start with 0x80 or 0xff)
Comment threadlib/large-numbers.js Outdated
@isaacs
isaacs merged commit 9a44de7 into isaacs:masterJun 1, 2019
@isaacs

Copy link
Copy Markdown
Owner

I see what happened here.

To encode files over 8gb, bsdtar drops the trailing 0x20, and uses that as a part of the octal-in-ascii number. This is an ambiguous part of the spec (such as it is), which gnutar interprets differently. Thankfully, bsdtar also prepends a PAX extended file attributes entry, which gnutar interprets properly. So, for example, a 10gb file would fill those 12 bytes with '120000000000', no terminator. Gnutar misinterprets this as 0o12000000000 (a mere 1.25 Gb), but that's overridden by the PAX header.

I'm not sure what bsdtar would write in that block if the file size couldn't fit in 12 octal digits, but I'm also not eager to create a 64 gb file on my laptop to find out.

@isaacs

Copy link
Copy Markdown
Owner

Actually I did get curious and checked. Bsdtar does the same thing as gnutar, but only when the file is 64gb or greater.

In short, this patch is good, it's landed, and published to latest. Thank you for digging in and fixing this. The reason it escaped my notice for so long is frankly that pax headers are so much more straightforward and make this type of bug irrelevant in so many cases.

The checks for Number.MAX_SAFE_INTEGER made me chuckle. I thought for a second that throwing a new error should be semver major bump, but if people are using this library to pack and unpack tarballs with 8 petabyte files in them, then the world is definitely in trouble.

@justfalter

Copy link
Copy Markdown
ContributorAuthor

Thanks for taking the time to go over this, @isaacs. I’ve got something upstream from my project that is explicitly producing gnu-formatted tarballs, for some reason.

Honestly, the only reason I even thought to do the min/max int checks were because you had tests that would have violated those checks. 8 petabyte files are pretty unlikely, but I wondered if there weren’t other numbers that might be encoded (uid, his, etc) that might someday exceed max int. I dug a bit into libarchive, and they have similar checks, there, as well.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@justfalter@isaacs@sdball
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Fix encoding/decoding of base-256 numbers by justfalter · Pull Request #215 · isaacs/node-tar · GitHub
Skip to content

Fix encoding/decoding of base-256 numbers - #215

Merged
isaacs merged 2 commits into
isaacs:masterfrom
justfalter:fix-base-256
Jun 1, 2019
Merged

Fix encoding/decoding of base-256 numbers#215
isaacs merged 2 commits into
isaacs:masterfrom
justfalter:fix-base-256

Conversation

@justfalter

@justfalterjustfalter commented May 30, 2019

Copy link
Copy Markdown
Contributor

This PR fixes issues I've identified with the handling of base-256 encoded numbers within node-tar (see #188). The issues would generally present themselves when attempting to extract a gnu-formatted tar entry for a file greater than 8gb in size.

  • The last byte of the buffer was incorrectly being ignored when encoding/decoding.
  • Javascript can only have safe integer precision for numbers between -9007199254740991 and 9007199254740991. Any numbers outside these bounds will see the lowest-order bits rounded off. For example, 9007199254749999 will be rounded to 9007199254750000.
  • I've modified large-integer.jsparse and encode functions to throw TypeError exceptions if they encounter a number that will not be precisely represented as a javascript integer, or if the buffer being decoded does not appear to be a base-256 encoded number (must start with 80 or ff).

- Encoding/decoding of base-256 numbers failed to failed to handle last
byte in buffer. Handling was previously broken.
- Take javascript's MAX_SAFE_INTEGER / MIN_SAFE_INTEGER into account
when encoding/decoding. Namely, if the numbers cannot accurately be
represented in javascript with integer-precision, a TypeError will be
thrown.
- Throw a TypeError if the parser is passed an buffer that does not
appear to be base-256 encoded. (must start with 0x80 or 0xff)
Comment threadlib/large-numbers.js Outdated
@isaacs
isaacs merged commit 9a44de7 into isaacs:masterJun 1, 2019
@isaacs

Copy link
Copy Markdown
Owner

I see what happened here.

To encode files over 8gb, bsdtar drops the trailing 0x20, and uses that as a part of the octal-in-ascii number. This is an ambiguous part of the spec (such as it is), which gnutar interprets differently. Thankfully, bsdtar also prepends a PAX extended file attributes entry, which gnutar interprets properly. So, for example, a 10gb file would fill those 12 bytes with '120000000000', no terminator. Gnutar misinterprets this as 0o12000000000 (a mere 1.25 Gb), but that's overridden by the PAX header.

I'm not sure what bsdtar would write in that block if the file size couldn't fit in 12 octal digits, but I'm also not eager to create a 64 gb file on my laptop to find out.

@isaacs

Copy link
Copy Markdown
Owner

Actually I did get curious and checked. Bsdtar does the same thing as gnutar, but only when the file is 64gb or greater.

In short, this patch is good, it's landed, and published to latest. Thank you for digging in and fixing this. The reason it escaped my notice for so long is frankly that pax headers are so much more straightforward and make this type of bug irrelevant in so many cases.

The checks for Number.MAX_SAFE_INTEGER made me chuckle. I thought for a second that throwing a new error should be semver major bump, but if people are using this library to pack and unpack tarballs with 8 petabyte files in them, then the world is definitely in trouble.

@justfalter

Copy link
Copy Markdown
ContributorAuthor

Thanks for taking the time to go over this, @isaacs. I’ve got something upstream from my project that is explicitly producing gnu-formatted tarballs, for some reason.

Honestly, the only reason I even thought to do the min/max int checks were because you had tests that would have violated those checks. 8 petabyte files are pretty unlikely, but I wondered if there weren’t other numbers that might be encoded (uid, his, etc) that might someday exceed max int. I dug a bit into libarchive, and they have similar checks, there, as well.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@justfalter@isaacs@sdball
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); Fix encoding/decoding of base-256 numbers by justfalter · Pull Request #215 · isaacs/node-tar · GitHub
Skip to content

Fix encoding/decoding of base-256 numbers - #215

Merged
isaacs merged 2 commits into
isaacs:masterfrom
justfalter:fix-base-256
Jun 1, 2019
Merged

Fix encoding/decoding of base-256 numbers#215
isaacs merged 2 commits into
isaacs:masterfrom
justfalter:fix-base-256

Conversation

@justfalter

@justfalterjustfalter commented May 30, 2019

Copy link
Copy Markdown
Contributor

This PR fixes issues I've identified with the handling of base-256 encoded numbers within node-tar (see #188). The issues would generally present themselves when attempting to extract a gnu-formatted tar entry for a file greater than 8gb in size.

  • The last byte of the buffer was incorrectly being ignored when encoding/decoding.
  • Javascript can only have safe integer precision for numbers between -9007199254740991 and 9007199254740991. Any numbers outside these bounds will see the lowest-order bits rounded off. For example, 9007199254749999 will be rounded to 9007199254750000.
  • I've modified large-integer.jsparse and encode functions to throw TypeError exceptions if they encounter a number that will not be precisely represented as a javascript integer, or if the buffer being decoded does not appear to be a base-256 encoded number (must start with 80 or ff).

- Encoding/decoding of base-256 numbers failed to failed to handle last
byte in buffer. Handling was previously broken.
- Take javascript's MAX_SAFE_INTEGER / MIN_SAFE_INTEGER into account
when encoding/decoding. Namely, if the numbers cannot accurately be
represented in javascript with integer-precision, a TypeError will be
thrown.
- Throw a TypeError if the parser is passed an buffer that does not
appear to be base-256 encoded. (must start with 0x80 or 0xff)
Comment threadlib/large-numbers.js Outdated
@isaacs
isaacs merged commit 9a44de7 into isaacs:masterJun 1, 2019
@isaacs

Copy link
Copy Markdown
Owner

I see what happened here.

To encode files over 8gb, bsdtar drops the trailing 0x20, and uses that as a part of the octal-in-ascii number. This is an ambiguous part of the spec (such as it is), which gnutar interprets differently. Thankfully, bsdtar also prepends a PAX extended file attributes entry, which gnutar interprets properly. So, for example, a 10gb file would fill those 12 bytes with '120000000000', no terminator. Gnutar misinterprets this as 0o12000000000 (a mere 1.25 Gb), but that's overridden by the PAX header.

I'm not sure what bsdtar would write in that block if the file size couldn't fit in 12 octal digits, but I'm also not eager to create a 64 gb file on my laptop to find out.

@isaacs

Copy link
Copy Markdown
Owner

Actually I did get curious and checked. Bsdtar does the same thing as gnutar, but only when the file is 64gb or greater.

In short, this patch is good, it's landed, and published to latest. Thank you for digging in and fixing this. The reason it escaped my notice for so long is frankly that pax headers are so much more straightforward and make this type of bug irrelevant in so many cases.

The checks for Number.MAX_SAFE_INTEGER made me chuckle. I thought for a second that throwing a new error should be semver major bump, but if people are using this library to pack and unpack tarballs with 8 petabyte files in them, then the world is definitely in trouble.

@justfalter

Copy link
Copy Markdown
ContributorAuthor

Thanks for taking the time to go over this, @isaacs. I’ve got something upstream from my project that is explicitly producing gnu-formatted tarballs, for some reason.

Honestly, the only reason I even thought to do the min/max int checks were because you had tests that would have violated those checks. 8 petabyte files are pretty unlikely, but I wondered if there weren’t other numbers that might be encoded (uid, his, etc) that might someday exceed max int. I dug a bit into libarchive, and they have similar checks, there, as well.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@justfalter@isaacs@sdball