commercialhaskell / stack

The Haskell Tool Stack
http://haskellstack.org
BSD 3-Clause "New" or "Revised" License
3.95k stars 842 forks source link

Put hash/checksum in stack.yaml.lock to prevent manual updating #6590

Open ysangkok opened 1 month ago

ysangkok commented 1 month ago

General summary/comments (optional)

We accidentally mangled our lock file when doing a global search/replace of a git hash.

The lock file ended up in a state where the URL didn't match the sha256, but it didn't result in any errors from stack.

Steps to reproduce

Mangle lock file.

Expected

I want stack to error next time it read the lock file, and tell me the lock file is corrupted.

Actual

No error

Stack version

stack --version
Version 2.15.7, Git revision f590e0165b5ab92f5f7f87f8aa55852e1972ee25 x86_64 hpack-0.36.0

Method of installation

Platform

Debian Bookworm

mpilgrem commented 1 month ago

@ysangkok, thanks for reporting. I've been looking at what pantry and Stack does, and it seems to me that when Stack needs the information in a *.lock file to be correct and it is not, Stack throws an error; and that when Stack can tolerate the information in a *.lock file being incorrect (that is, Stack has other options to get what is specified) it takes those other options. I am conscious that lock files are provided for reasons of convenience and performance, so I am cautious about changes that might adversely affect that.

Can we work though what alternative behaviour you are seeking with a simple example, say a simple one-package project called foo (stack new foo) with an extra-dep on acme-missiles-0.3? Can you specify what form of corruption of the *.lock file you think should disable Stack, but does not?

mpilgrem commented 1 month ago

In particular:

ysangkok commented 1 month ago

Can we work though what alternative behaviour you are seeking with a simple example, say a simple one-package project called foo (stack new foo) with an extra-dep on acme-missiles-0.3? Can you specify what form of corruption of the *.lock file you think should disable Stack, but does not?

Yes. After making such a demo project with stack new, I add acme-missiles-0.1.0.0 to stack.yaml and package.yaml, and I adjust app/Main.hs to use launchMissiles. I compile and run using stack run. It works as expected (doesn't print anything because this version of acme-missiles forks a thread that delays a bit)

Then, I modify stack.yaml.lock to say

# This file was autogenerated by Stack.
# You should not edit this file by hand.
# For more information, please see the documentation at:
#   https://docs.haskellstack.org/en/stable/lock_files

packages:
- completed:
    hackage: acme-missiles-0.1.0.0@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff,100
    pantry-tree:
      sha256: 8b0c94f34a544aa55e4861fc26288a0d77abed40d81f547b0e53c20309549e21
      size: 165
  original:
    hackage: acme-missiles-0.1.0.0
snapshots:
- completed:
    sha256: 73ad581de7c5306278aec7706cafaf3b1c2eb7abf4ab586e4d9dc675c6106c4e
    size: 718708
    url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/22/23.yaml
  original:
    url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/22/23.yaml

The Hackage hash is bad now, and the size too (I think that's what the ,100 is?).

But if I execute stack clean && stack run, the corruption is still there. And Stack doesn't detect the corruption of the lock file.

In my original version, acme-missiles was pinned with a git hash. This kind of corruption seems more likely, since people use these hashes to identify dependencies. Since acme-missiles isn't on git, I can't do that kind of corruption. But I think the corruption done in this message would also be fixed if the Stack had some kind of protection against manual editing.

mpilgrem commented 1 month ago

@ysangkok, in that example, Stack builds acme-missles-0.1.0.0 and adds it to your immutable snapshot database in the Stack root. Having done that, it ignores the SHA 256 provided by the lock file as it is using the package version in the database. That is why stack run does not complain.

I think something similar would happen with an extra-dep that is a git repository at a specific commit.