Added qhelp for UnhandledStreamPipe query

This commit is contained in:
Napalys Klicius
2025-05-23 13:35:36 +02:00
parent c6db32ed73
commit 248f83c4db
4 changed files with 83 additions and 0 deletions

View File

@@ -0,0 +1,44 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
In Node.js, calling the <code>pipe()</code> method on a stream without proper error handling can lead to silent failures, where errors are dropped and not propagated downstream. This can result in unexpected behavior and make debugging difficult. It is crucial to ensure that error handling is implemented when using stream pipes to maintain the reliability of the application.
</p>
</overview>
<recommendation>
<p>
Instead of using <code>pipe()</code> with manual error handling, prefer using the <code>pipeline</code> function from the Node.js stream module. The <code>pipeline</code> function automatically handles errors and ensures proper cleanup of resources. This approach is more robust and eliminates the risk of forgetting to handle errors.
</p>
<p>
If you must use <code>pipe()</code>, always attach an error handler to the source stream using methods like <code>on('error', handler)</code> to ensure that any errors during the streaming process are properly handled.
</p>
</recommendation>
<example>
<p>
The following code snippet demonstrates a problematic usage of the <code>pipe()</code> method without error handling:
</p>
<sample src="examples/UnhandledStreamPipe.js" />
<p>
A better approach is to use the <code>pipeline</code> function, which automatically handles errors:
</p>
<sample src="examples/UnhandledStreamPipeGood.js" />
<p>
Alternatively, if you need to use <code>pipe()</code>, make sure to add error handling:
</p>
<sample src="examples/UnhandledStreamPipeManualError.js" />
</example>
<references>
<li>Node.js Documentation: <a href="https://nodejs.org/api/stream.html#streampipelinestreams-callback">stream.pipeline()</a>.</li>
</references>
</qhelp>

View File

@@ -0,0 +1,6 @@
const fs = require('fs');
const source = fs.createReadStream('source.txt');
const destination = fs.createWriteStream('destination.txt');
// Bad: No error handling
source.pipe(destination);

View File

@@ -0,0 +1,17 @@
const { pipeline } = require('stream');
const fs = require('fs');
const source = fs.createReadStream('source.txt');
const destination = fs.createWriteStream('destination.txt');
// Good: Using pipeline for automatic error handling
pipeline(
source,
destination,
(err) => {
if (err) {
console.error('Pipeline failed:', err);
} else {
console.log('Pipeline succeeded');
}
}
);

View File

@@ -0,0 +1,16 @@
const fs = require('fs');
const source = fs.createReadStream('source.txt');
const destination = fs.createWriteStream('destination.txt');
// Alternative Good: Manual error handling with pipe()
source.on('error', (err) => {
console.error('Source stream error:', err);
destination.destroy(err);
});
destination.on('error', (err) => {
console.error('Destination stream error:', err);
source.destroy(err);
});
source.pipe(destination);