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

Some possible bugs concerning fs.appendFile() and fs.writeFile() #11595

Closed
vsemozhetbyt opened this issue Feb 28, 2017 · 9 comments
Closed

Some possible bugs concerning fs.appendFile() and fs.writeFile() #11595

vsemozhetbyt opened this issue Feb 28, 2017 · 9 comments
Labels
confirmed-bug Issues with confirmed bugs. fs Issues and PRs related to the fs subsystem / file system. good first issue Issues that are suitable for first-time contributors.

Comments

@vsemozhetbyt
Copy link
Contributor

vsemozhetbyt commented Feb 28, 2017

  • Version: 7.6.0
  • Platform: Windows 7 x64
  • Subsystem: fs, test

1. fs.appendFile() and fs.writeFile() can be called without mandatory data parameter, while not throwing any error messages. Thus, the only second parameter serves as data and callback (mandatory as well) parameters at the same time.

const fs = require('fs');

const cb = (err) => { if(err) console.error(err); }

fs.appendFile('append-file.txt', cb);
fs.writeFile('write-file.txt', cb);

This code runs without any errors and produces 2 files with the same content:

> cat append-file.txt
(err) => { if(err) console.error(err); }
> cat write-file.txt
(err) => { if(err) console.error(err); }

It seems this is hardly an expected behavior.

2. test/parallel/test-fs-null-bytes.js tests these functions with wrong parameters scheme, i.e. without mandatory data parameter. This may be not very important for the test aim, but it makes it somehow compromised.

@mscdex mscdex added the fs Issues and PRs related to the fs subsystem / file system. label Feb 28, 2017
@gireeshpunathil
Copy link
Member

Agreed that this is indeed an issue.
Modifying the callback thus:

const cb = (err) => { if(err) console.error(err); else console.log('well done!');}

shows that 'cb' is used as data, as well as the callback.

Looking at the writeFile implementation fs.watchFile I see that the callback and the data being extracted without cohesion between them, as the root case. For example, callback is extracted as the last param, and data is extracted as the second param. No assertion is made to make sure they are discretely different, and mandatory, as the per the API doc:
fs.writeFile(file, data[, options], callback)

@seishun seishun added good first issue Issues that are suitable for first-time contributors. confirmed-bug Issues with confirmed bugs. labels Feb 28, 2017
@vsemozhetbyt
Copy link
Contributor Author

PR for the second issue.

@seishun
Copy link
Contributor

seishun commented Feb 28, 2017

@vsemozhetbyt Just curious, how did you find out that test/parallel/test-fs-null-bytes.js is problematic?

@vsemozhetbyt
Copy link
Contributor Author

vsemozhetbyt commented Feb 28, 2017

@seishun I was trying to eliminate deopts in some fs functions and was going over possible fixes. One of these fixes was to replace this line in the fs.writeFile():
callback = maybeCallback(arguments[arguments.length - 1]);
by this one:
callback = maybeCallback(callback || options);
Then I have built and have run tests and only test/parallel/test-fs-null-bytes.js has failed, so I went at it)

seishun pushed a commit that referenced this issue Mar 3, 2017
The functions `fs.appendFile()` and `fs.writeFile()`
were being called without the required `data` argument.

Refs: #11595
PR-URL: #11601
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Nikolai Vavilov <vvnicholas@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Yuta Hiroto <hello@about-hiroppy.com>
addaleax pushed a commit that referenced this issue Mar 5, 2017
The functions `fs.appendFile()` and `fs.writeFile()`
were being called without the required `data` argument.

Refs: #11595
PR-URL: #11601
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Nikolai Vavilov <vvnicholas@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Yuta Hiroto <hello@about-hiroppy.com>
@ghaiklor
Copy link
Contributor

ghaiklor commented Mar 23, 2017

yeah, writeFile doesn't have a check for data.

fs.writeFile = function(path, data, options, callback) {
  callback = maybeCallback(arguments[arguments.length - 1]);
  options = getOptions(options, { encoding: 'utf8', mode: 0o666, flag: 'w' });
  // ...
}

So, in @vsemozhetbyt case, data is a callback and a data at the same time, which leads to converting a function into string and writing it into file as data and calling it as a callback since it's the last one argument from the list.

What if we will add a small check here:

fs.writeFile = function(path, data, options, callback) {
  if (typeof data === 'function') throw new Error('you need to specify data');

  callback = maybeCallback(arguments[arguments.length - 1]);
  options = getOptions(options, { encoding: 'utf8', mode: 0o666, flag: 'w' });
  // ...
}

I believe that order (path: String, data: Buffer) is strict here and we can just check if data is a function or not.

What you think?

UPD: I like @vsemozhetbyt 's approach with maybeCallback(callback || options), though I'm not sure if we can throw an error Calling an asynchronous function without callback is deprecated.. May be better to throw an error with direct message about data argument.

@vsemozhetbyt
Copy link
Contributor Author

@ghaiklor There is a PR that tries to fix this in a different way, but it has hung a little. Let's see how it will proceed)

@ghaiklor
Copy link
Contributor

@vsemozhetbyt BTW, it can be closed due works as expected, since docs are saying that you need to specify 3 arguments and only options is optional 😸

@vsemozhetbyt
Copy link
Contributor Author

vsemozhetbyt commented Mar 23, 2017

@ghaiklor Let's have an eccentric method for a change)

MylesBorins pushed a commit that referenced this issue Apr 18, 2017
The functions `fs.appendFile()` and `fs.writeFile()`
were being called without the required `data` argument.

Refs: #11595
Backport-PR-URL: #12477
PR-URL: #11601
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Nikolai Vavilov <vvnicholas@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Yuta Hiroto <hello@about-hiroppy.com>
MylesBorins pushed a commit that referenced this issue Apr 19, 2017
The functions `fs.appendFile()` and `fs.writeFile()`
were being called without the required `data` argument.

Refs: #11595
Backport-PR-URL: #12477
PR-URL: #11601
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Nikolai Vavilov <vvnicholas@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Yuta Hiroto <hello@about-hiroppy.com>
@seishun
Copy link
Contributor

seishun commented Jun 13, 2017

Fixed in 208db56.

@seishun seishun closed this as completed Jun 13, 2017
andrew749 pushed a commit to michielbaird/node that referenced this issue Jul 19, 2017
The functions `fs.appendFile()` and `fs.writeFile()`
were being called without the required `data` argument.

Refs: nodejs/node#11595
Backport-PR-URL: nodejs/node#12477
PR-URL: nodejs/node#11601
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Nikolai Vavilov <vvnicholas@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Yuta Hiroto <hello@about-hiroppy.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
confirmed-bug Issues with confirmed bugs. fs Issues and PRs related to the fs subsystem / file system. good first issue Issues that are suitable for first-time contributors.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants