webpack icon indicating copy to clipboard operation
webpack copied to clipboard

Circular hash dependency for hashed folder names

Open victormoukhortov opened this issue 4 years ago • 23 comments

The same https://github.com/webpack/webpack/issues/16858


Bug report

What is the current behavior?

A Circular hash dependency compilation error is thrown for hash collisions in folder names.

If the current behavior is a bug, please provide the steps to reproduce.

Applying this patch to my webpack config (from create-react-app):

diff --git a/config/webpack/webpack.config.ts b/config/webpack/webpack.config.ts
index fc4bca3fc3..3bd779a7c1 100644
--- a/config/webpack/webpack.config.ts
+++ b/config/webpack/webpack.config.ts
@@ -273,13 +273,13 @@ const config = function (webpackEnv: Configuration['mode'], target = 'web'): Con
           // There will be one main bundle, and one file per asynchronous chunk.
           // In development, it does not produce real files.
           filename: isEnvProduction
-            ? 'static/js/[name].[contenthash:8].js'
+            ? 'static/js/[contenthash:2]/[name].[contenthash:8].js'
             : isEnvDevelopment
             ? 'static/js/bundle.js'
             : undefined,
           // There are also additional JS chunk files if you use code splitting.
           chunkFilename: isEnvProduction
-            ? 'static/js/[name].[contenthash:8].chunk.js'
+            ? 'static/js/[contenthash:2]/[name].[contenthash:8].chunk.js'
             : isEnvDevelopment
             ? 'static/js/[name].chunk.js'
             : undefined,
@@ -715,8 +715,8 @@ const config = function (webpackEnv: Configuration['mode'], target = 'web'): Con
               new MiniCssExtractPlugin({
                 // Options similar to the same options in webpackOptions.output
                 // both options are optional
-                filename: 'static/css/[name].[contenthash:8].css',
-                chunkFilename: 'static/css/[name].[contenthash:8].chunk.css'
+                filename: 'static/css/[contenthash:2]/[name].[contenthash:8].css',
+                chunkFilename: 'static/css/[contenthash:2]/[name].[contenthash:8].chunk.css'
               }),
             // Generate an asset manifest file with the following content:
             // - "files" key: Mapping of all asset filenames to their corresponding

produces a Circular hash dependency compilation error. I suspect a reasonably large project and/or many chunks would be required to reliably produce a collision.

What is the expected behavior?

I expect content hash collisions to be tolerated for folder names.

Other relevant information: webpack version: 5.51.1 Node.js version: 14.17.5 Operating System: Tested on OSX & Linux

victormoukhortov avatar Aug 24 '21 19:08 victormoukhortov

Please provide steps to reproduce

alexander-akait avatar Aug 25 '21 10:08 alexander-akait

@alexander-akait

  1. Make a large project, big enough to produce hash collisions in chunks
  2. Configure webpack to include content hashes in output folder names
  3. Observe the error

victormoukhortov avatar Aug 25 '21 14:08 victormoukhortov

I ask to provide because hash collision is not easy to reproduce and debug

alexander-akait avatar Aug 25 '21 14:08 alexander-akait

Note, shorted hash is always has hash collision

alexander-akait avatar Aug 25 '21 14:08 alexander-akait

You should not use value is less than 8

alexander-akait avatar Aug 25 '21 14:08 alexander-akait

You should not use value is less than 8

If you read my report, I wrote that I expect content hash collisions to be tolerated for folder names. Can you explain why this is an invalid assumption? It worked fine in webpack 4.

victormoukhortov avatar Aug 25 '21 16:08 victormoukhortov

Because webpack v4 do not has real content hash values, now we replace all urls/links/imports on real content hash, so there is place for collision

alexander-akait avatar Aug 25 '21 16:08 alexander-akait

It should be possible to place two chunk files with non-colliding 8-character hashes into a folder with colliding 2-character hashes.

victormoukhortov avatar Aug 25 '21 16:08 victormoukhortov

There are limitations as I described above

alexander-akait avatar Aug 25 '21 16:08 alexander-akait

I don't see why the hash replacement mechanism can't check if it's a folder name or a file name before throwing.

victormoukhortov avatar Aug 25 '21 17:08 victormoukhortov

Okay, feel free to send a PR, if you think it is easy

alexander-akait avatar Aug 25 '21 17:08 alexander-akait

And, yes, when we generate hashes, no files and directories exists, writing them happens only after hashes were calculated

alexander-akait avatar Aug 25 '21 17:08 alexander-akait

I never said it's easy, only that it's expected functionality that worked in v4.

victormoukhortov avatar Aug 25 '21 18:08 victormoukhortov

You can disable real content hashing with output.realContentHash: false to get the webpack 4 behavior.

sokra avatar Sep 03 '21 19:09 sokra

Another the same problem https://github.com/webpack/webpack/issues/14574, contenthash can overlap with existing value in source code, for example:

var f=[1,1.387039845,1.306562965,1.175875602,1,.785694958,.5411961,.275899379]

And 785694958 can be override on hash (collision). To solve it we need keep places for replacing

alexander-akait avatar Oct 26 '21 11:10 alexander-akait

This issue had no activity for at least three months.

It's subject to automatic issue closing if there is no activity in the next 15 days.

webpack-bot avatar Jan 25 '22 11:01 webpack-bot

bump

alexander-akait avatar Jan 25 '22 11:01 alexander-akait

closing in favor of https://github.com/webpack/webpack/issues/15288

vankop avatar Feb 02 '22 13:02 vankop

@vankop It is another problem

alexander-akait avatar Feb 02 '22 13:02 alexander-akait

Let's keep open

alexander-akait avatar Feb 02 '22 13:02 alexander-akait

Issue was closed because of inactivity.

If you think this is still a valid issue, please file a new issue with additional information.

webpack-bot avatar May 20 '22 06:05 webpack-bot

It looks like this is still an issue, is there a way to prevent it from being auto-closed?

This behaviour is quite difficult to catch and can cause catastrophic failures in builds (in our case, it was replacing moduleids so dynamic imports would fail)

Edit: For others, we fixed this issue by changing our hash length from 5 to 10. Anything less than 5 or 6 can easily collide with module IDs which are numerical

taurheim avatar Oct 12 '23 16:10 taurheim

I can't stress how dangerous this bug can be. We use [contenthash:8]/chunk-[contenthash].min.js as chunkFilename so that the chunks are namespaced in different folders rather than a single one (such namespacing being required on very large S3 buckets to avoid some stability issues).

As the size of our application grew we started to hit very regular overlaps, which end up corrupting the generated files. Since they may hide inside lazy-loaded chunks, CI tests may fail to detect these errors, eventually causing a broken build to reach production. We managed to avoid that so far, but it's a very uncomfortable position to be in. We can't increase the hash length, as otherwise the namespacing will be too granular and the S3 issues may come back.

We're now running a pass after each Webpack build to ensure the generated files are correct. It's not perfect however (Webpack may generate a corrupted but syntactically valid file), so we're still hoping to find a better fix.

arcanis avatar Dec 12 '23 16:12 arcanis