Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

src: don't match after -- in Dotenv::GetPathFromArgs #54237

Merged
merged 1 commit into from
Aug 13, 2024

Conversation

RedYetiDev
Copy link
Member

@RedYetiDev RedYetiDev commented Aug 7, 2024

Fixes #54232

@nodejs-github-bot nodejs-github-bot added c++ Issues and PRs that require attention from people who are familiar with C++. needs-ci PRs that need a full CI run. labels Aug 7, 2024
@RedYetiDev RedYetiDev added the dotenv Issues and PRs related to .env file parsing label Aug 7, 2024
Copy link
Member

@anonrig anonrig left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests are needed

@RedYetiDev
Copy link
Member Author

Is there is a specific file I should put the tests in? If not, I'll make a new file for them, but I wanted to make sure first.

Copy link

codecov bot commented Aug 7, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 87.10%. Comparing base (3ed9f98) to head (498011e).
Report is 460 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #54237      +/-   ##
==========================================
- Coverage   87.10%   87.10%   -0.01%     
==========================================
  Files         647      647              
  Lines      181739   181755      +16     
  Branches    34886    34886              
==========================================
+ Hits       158307   158317      +10     
- Misses      16740    16742       +2     
- Partials     6692     6696       +4     
Files with missing lines Coverage Δ
src/node_dotenv.cc 81.70% <100.00%> (+0.11%) ⬆️

... and 28 files with indirect coverage changes

@tniessen
Copy link
Member

tniessen commented Aug 7, 2024

optimizes the Dotenv::GetPathFromArgs function to not rely on string copying (strncmp)

Could you elaborate on that? strncmp itself does not copy anything.

@RedYetiDev
Copy link
Member Author

strncmp itself does not copy anything.

I don't know too much about CPP internals, so I may have got that part wrong. From what I understood, it's faster to use .find than find_if. I can do a quick benchmark to verify if you'd like?

@tniessen
Copy link
Member

tniessen commented Aug 7, 2024

I am not familiar with this part of the code base, but any iteration here is just going over the few, typically very short strings that were passed as command-line arguments, right? If this patch actually prevents copying unnecessarily, please explain that and I'm probably going to be in favor of such a change. Optimizing iteration over a few hundred characters, on the other hand, seems like it will be of little benefit.

src/node_dotenv.cc Show resolved Hide resolved
@RedYetiDev RedYetiDev changed the title src: optimize Dotenv::GetPathFromArgs src: don't match after -- in Dotenv::GetPathFromArgs Aug 7, 2024
@RedYetiDev RedYetiDev requested a review from anonrig August 7, 2024 20:04
@xduugu
Copy link
Contributor

xduugu commented Aug 7, 2024

Thanks a lot for working on a fix, @RedYetiDev.

I just noticed I also included the -- separator in the commands that execute a script file in my original bug report (I just edited it). However, the separator should not be required in these cases:

node works.js --env-file nonexistent-file

So the argument processing need to stop when this condition is true:

arg == "--" || !arg.starts_with("-")

When looking at the code, I noticed another bug: every argument that starts with --env-file is recognized as --env-file, for example --env-file-asdf:

node --env-file-asdf nonexistent-file
node --env-file-asdf=nonexistent-file

both exit with

node: nonexistent-file: not found

@RedYetiDev
Copy link
Member Author

RedYetiDev commented Aug 7, 2024

When looking at the code, I noticed another bug: every argument that starts with --env-file is recognized as --env-file, for example --env-file-asdf:

That is indeed an issue, @anonrig do you want me to patch it here or in another PR?
(I can patch it here in a seperate commit?)

@@ -14,21 +14,23 @@ using v8::String;
std::vector<std::string> Dotenv::GetPathFromArgs(
const std::vector<std::string>& args) {
const auto find_match = [](const std::string& arg) {
const std::string_view flag = "--env-file";
return strncmp(arg.c_str(), flag.data(), flag.size()) == 0;
return arg == "--" || arg.starts_with("--env-file");
Copy link
Member Author

@RedYetiDev RedYetiDev Aug 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return arg == "--" || arg.starts_with("--env-file");
return arg == "--" || arg == "--env-file" || arg.starts_with("--env-file=");

This is the patch for the behavior described:

(before)
└─$ node --env-file-ABCD TEST  
node: TEST: not found
(after)
└─$ node --env-file-ABCD TEST
node: bad option: --env-file-ABCD

@xduugu
Copy link
Contributor

xduugu commented Aug 7, 2024

@anonrig The for loop @RedYetiDev used was much easier to understand for me. It might be less sophisticated (and a little less performant) as the current code, but wouldn't something like the following be a lot more readable? (probably no valid c++ code)

std::vector<std::string> Dotenv::GetPathFromArgs(const std::vector<std::string>& args) {
    const std::string_view flag = "--env-file";
    std::vector<std::string> paths;

    for (size_t i = 0; i < args.size(); ++i) {
        const std::string_view arg = args[i];

        // argument separator or script file
        if (arg == "--" || !arg.starts_with("-")) {
            break;
        }

        // --env-file <file>
        if (arg == flag) {
            if (i + 1 < args.size()) {
                paths.push_back(args[i + 1]);
                ++i;
            }
            // TODO else error?
        // --env-file=<file>
        } else if (arg.starts_with(flag + "=") {
            paths.push_back(std::string(arg.substr(flag.size() + 1)));
        }
    }

    return paths;
}

@RedYetiDev
Copy link
Member Author

@anonrig The for loop @RedYetiDev used was much easier to understand for me. It might be less sophisticated (and a little less performant) as the current code, but wouldn't something like the following be a lot more readable? (probably no valid c++ code)

I'm planning to re-try the loop again in a new PR once this lands.

src/node_dotenv.cc Show resolved Hide resolved
src/node_dotenv.cc Outdated Show resolved Hide resolved
Co-Authored-By: Cedric Staniewski <cedric@gmx.ca>
@anonrig anonrig added the request-ci Add this label to start a Jenkins CI on a PR. label Aug 8, 2024
@github-actions github-actions bot removed the request-ci Add this label to start a Jenkins CI on a PR. label Aug 8, 2024
@nodejs-github-bot
Copy link
Collaborator

@anonrig
Copy link
Member

anonrig commented Aug 8, 2024

@anonrig is there a reason this function is separate from the parsing of other, similar arguments? (Like -e and -p)?

--env-file supports NODE_OPTIONS. therefore, it needs to be executed/analyzed before V8 is initialized.

@RedYetiDev
Copy link
Member Author

FWIW once this lands, I'll open a seperate PR re-writing the function in a way that fixes all these little bugs mentioned:

std::vector<std::string> Dotenv::GetPathFromArgs(
    const std::vector<std::string>& args) {
  std::vector<std::string> paths;
  for (size_t i = 1; i < args.size(); ++i) {
    const auto& arg = args[i];

    if (arg == "--" || arg[0] != '-') {
      break;
    }

    if (arg.starts_with("--env-file=")) {
      paths.push_back(arg.substr(11));  // Directly extract the path
    } else if (arg == "--env-file" && i + 1 < args.size()) {
      paths.push_back(args[++i]);  // Advance to the next argument
    }
  }
  return paths;
}

@RedYetiDev
Copy link
Member Author

author ready?:

@nodejs-github-bot
Copy link
Collaborator

@RedYetiDev
Copy link
Member Author

RedYetiDev commented Aug 12, 2024

Hey, I think this is ready to land. No objections and a passing CI :-)

No rush tho

@anonrig anonrig added the commit-queue Add this label to land a pull request using GitHub Actions. label Aug 12, 2024
@nodejs-github-bot nodejs-github-bot added commit-queue-failed An error occurred while landing this pull request using GitHub Actions. and removed commit-queue Add this label to land a pull request using GitHub Actions. labels Aug 12, 2024
@nodejs-github-bot
Copy link
Collaborator

Commit Queue failed
- Loading data for nodejs/node/pull/54237
✔  Done loading data for nodejs/node/pull/54237
----------------------------------- PR info ------------------------------------
Title      src: don't match after `--` in `Dotenv::GetPathFromArgs` (#54237)
   ⚠  Could not retrieve the email or name of the PR author's from user's GitHub profile!
Branch     RedYetiDev:dotenv-fix -> nodejs:main
Labels     c++, needs-ci, dotenv
Commits    1
 - src: don't match after `--` in `Dotenv::GetPathFromArgs`
Committers 1
 - RedYetiDev <38299977+RedYetiDev@users.noreply.github.com>
PR-URL: https://github.com/nodejs/node/pull/54237
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
------------------------------ Generated metadata ------------------------------
PR-URL: https://github.com/nodejs/node/pull/54237
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
--------------------------------------------------------------------------------
   ℹ  This PR was created on Wed, 07 Aug 2024 00:11:34 GMT
   ✔  Approvals: 1
   ✔  - Yagiz Nizipli (@anonrig) (TSC): https://github.com/nodejs/node/pull/54237#pullrequestreview-2226545215
   ✘  This PR needs to wait 35 more hours to land (or 0 hours if there is one more approval)
   ✔  Last GitHub CI successful
   ℹ  Last Full PR CI on 2024-08-10T19:46:38Z: https://ci.nodejs.org/job/node-test-pull-request/61004/
- Querying data for job/node-test-pull-request/61004/
   ✔  Last Jenkins CI successful
--------------------------------------------------------------------------------
   ✔  Aborted `git node land` session in /home/runner/work/node/node/.ncu
https://github.com/nodejs/node/actions/runs/10351730728

@BoscoDomingo
Copy link
Contributor

FWIW once this lands, I'll open a seperate PR re-writing the function in a way that fixes all these little bugs mentioned:

std::vector<std::string> Dotenv::GetPathFromArgs(
    const std::vector<std::string>& args) {
  std::vector<std::string> paths;
  for (size_t i = 1; i < args.size(); ++i) {
    const auto& arg = args[i];

    if (arg == "--" || arg[0] != '-') {
      break;
    }

    if (arg.starts_with("--env-file=")) {
      paths.push_back(arg.substr(11));  // Directly extract the path
    } else if (arg == "--env-file" && i + 1 < args.size()) {
      paths.push_back(args[++i]);  // Advance to the next argument
    }
  }
  return paths;
}

I already did change that piece of code in #53060. Might want to add there?

@anonrig anonrig added commit-queue Add this label to land a pull request using GitHub Actions. and removed commit-queue-failed An error occurred while landing this pull request using GitHub Actions. labels Aug 13, 2024
@nodejs-github-bot nodejs-github-bot added commit-queue-failed An error occurred while landing this pull request using GitHub Actions. and removed commit-queue Add this label to land a pull request using GitHub Actions. labels Aug 13, 2024
@nodejs-github-bot
Copy link
Collaborator

Commit Queue failed
- Loading data for nodejs/node/pull/54237
✔  Done loading data for nodejs/node/pull/54237
----------------------------------- PR info ------------------------------------
Title      src: don't match after `--` in `Dotenv::GetPathFromArgs` (#54237)
   ⚠  Could not retrieve the email or name of the PR author's from user's GitHub profile!
Branch     RedYetiDev:dotenv-fix -> nodejs:main
Labels     c++, needs-ci, dotenv
Commits    1
 - src: don't match after `--` in `Dotenv::GetPathFromArgs`
Committers 1
 - RedYetiDev <38299977+RedYetiDev@users.noreply.github.com>
PR-URL: https://github.com/nodejs/node/pull/54237
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
------------------------------ Generated metadata ------------------------------
PR-URL: https://github.com/nodejs/node/pull/54237
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
--------------------------------------------------------------------------------
   ℹ  This PR was created on Wed, 07 Aug 2024 00:11:34 GMT
   ✔  Approvals: 1
   ✔  - Yagiz Nizipli (@anonrig) (TSC): https://github.com/nodejs/node/pull/54237#pullrequestreview-2226545215
   ✘  This PR needs to wait 1 more hours to land (or 0 hours if there is one more approval)
   ✔  Last GitHub CI successful
   ℹ  Last Full PR CI on 2024-08-12T12:21:23Z: https://ci.nodejs.org/job/node-test-pull-request/61004/
- Querying data for job/node-test-pull-request/61004/
   ✔  Last Jenkins CI successful
--------------------------------------------------------------------------------
   ✔  Aborted `git node land` session in /home/runner/work/node/node/.ncu
https://github.com/nodejs/node/actions/runs/10378367203

@aduh95 aduh95 added commit-queue Add this label to land a pull request using GitHub Actions. and removed commit-queue-failed An error occurred while landing this pull request using GitHub Actions. labels Aug 13, 2024
@nodejs-github-bot nodejs-github-bot removed the commit-queue Add this label to land a pull request using GitHub Actions. label Aug 13, 2024
@nodejs-github-bot nodejs-github-bot merged commit 880c446 into nodejs:main Aug 13, 2024
70 checks passed
@nodejs-github-bot
Copy link
Collaborator

Landed in 880c446

targos pushed a commit that referenced this pull request Aug 14, 2024
Co-Authored-By: Cedric Staniewski <cedric@gmx.ca>
PR-URL: #54237
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
targos pushed a commit that referenced this pull request Aug 14, 2024
Co-Authored-By: Cedric Staniewski <cedric@gmx.ca>
PR-URL: #54237
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
@RafaelGSS RafaelGSS mentioned this pull request Aug 19, 2024
@targos targos added the backport-requested-v20.x PRs awaiting manual backport to the v20.x-staging branch. label Sep 21, 2024
@targos
Copy link
Member

targos commented Sep 21, 2024

This would need a backport to land on v22.x as it uses C++20 features.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport-requested-v20.x PRs awaiting manual backport to the v20.x-staging branch. c++ Issues and PRs that require attention from people who are familiar with C++. dotenv Issues and PRs related to .env file parsing needs-ci PRs that need a full CI run.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Script argument --env-file is wrongly used as node option
8 participants