Skip to main content

์‚ฌ์šฉ์ž ์ง€์ • ์ฟผ๋ฆฌ ํ…Œ์ŠคํŠธ

CodeQL ์ฟผ๋ฆฌ์— ๋Œ€ํ•œ ํ…Œ์ŠคํŠธ๋ฅผ ์„ค์ •ํ•˜์—ฌ CodeQL CLI์˜ ์ƒˆ ๋ฆด๋ฆฌ์Šค๋กœ ์˜ˆ์ƒ ๊ฒฐ๊ณผ๋ฅผ ๊ณ„์† ๋ฐ˜ํ™˜ํ•˜๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ˆ„๊ฐ€ ์ด ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‚˜์š”?

CodeQL์€(๋Š”) ๋‹ค์Œ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ์œ ํ˜•์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • GitHub.com์˜ ํผ๋ธ”๋ฆญ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ, GitHub CodeQL ์‚ฌ์šฉ ์•ฝ๊ด€ ์ฐธ์กฐ
  • GitHub Code Security๊ฐ€ ํ™œ์„ฑํ™”๋œ GitHub Team ๋˜๋Š” GitHub Enterprise Cloud์˜ ์กฐ์ง ์†Œ์œ  ๋ฆฌํฌ์ง€ํ† ๋ฆฌ

์‚ฌ์šฉ์ž ์ง€์ • ์ฟผ๋ฆฌ ํ…Œ์ŠคํŠธ ์ •๋ณด

CodeQL(์€)๋Š” ์ฟผ๋ฆฌ์˜ ์ž๋™ํ™”๋œ ์žฌ๋ฐœ ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•œ ๊ฐ„๋‹จํ•œ ํ…Œ์ŠคํŠธ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์ฟผ๋ฆฌ๋ฅผ ํ…Œ์ŠคํŠธํ•˜์—ฌ ์˜ˆ์ƒ๋Œ€๋กœ ์ž‘๋™ํ•˜๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

์ฟผ๋ฆฌ ํ…Œ์ŠคํŠธ ์ค‘์— CodeQL์€(๋Š”) ์‚ฌ์šฉ์ž๊ฐ€ ์ฟผ๋ฆฌ๊ฐ€ ์ƒ์„ฑ๋  ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒํ•˜๋Š” ๊ฒฐ๊ณผ๋ฅผ ์‹ค์ œ๋กœ ์ƒ์„ฑ๋œ ๊ฒฐ๊ณผ์™€ ๋น„๊ตํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ์ƒ ๊ฒฐ๊ณผ์™€ ์‹ค์ œ ๊ฒฐ๊ณผ๊ฐ€ ๋‹ค๋ฅด๋ฉด ์ฟผ๋ฆฌ ํ…Œ์ŠคํŠธ๊ฐ€ ์‹คํŒจํ•ฉ๋‹ˆ๋‹ค. ํ…Œ์ŠคํŠธ๋ฅผ ์ˆ˜์ •ํ•˜๋ ค๋ฉด ์‹ค์ œ ๊ฒฐ๊ณผ์™€ ์˜ˆ์ƒ ๊ฒฐ๊ณผ๊ฐ€ ์ •ํ™•ํžˆ ์ผ์น˜ํ•  ๋•Œ๊นŒ์ง€ ์ฟผ๋ฆฌ ๋ฐ ์˜ˆ์ƒ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜๋ณตํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด ํ•ญ๋ชฉ์—์„œ๋Š” test run ํ•˜์œ„ ๋ช…๋ น์„ ์‚ฌ์šฉํ•˜์—ฌ ํ…Œ์ŠคํŠธ ํŒŒ์ผ์„ ๋งŒ๋“ค๊ณ  ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ ์ค๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž ์ง€์ • ์ฟผ๋ฆฌ์— ๋Œ€ํ•œ ํ…Œ์ŠคํŠธ CodeQL ํŒฉ ์„ค์ •

๋ชจ๋“  CodeQL ํ…Œ์ŠคํŠธ๋Š” ํŠน์ˆ˜ํ•œ "ํ…Œ์ŠคํŠธ" CodeQL ํŒฉ์— ์ €์žฅํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ๋‹ค์Œ์„ ์ •์˜ํ•˜๋Š” qlpack.yml ํŒŒ์ผ์ด ์žˆ๋Š” ํ…Œ์ŠคํŠธ ํŒŒ์ผ์˜ ๋””๋ ‰ํ„ฐ๋ฆฌ์ž…๋‹ˆ๋‹ค.

name: <name-of-test-pack>
version: 0.0.0
dependencies:
  <codeql-libraries-and-queries-to-test>: "*"
extractor: <language-of-code-to-test>

์ด dependencies ๊ฐ’์€ ํ…Œ์ŠคํŠธํ•  ์ฟผ๋ฆฌ๊ฐ€ ํฌํ•จ๋œ CodeQL ํŒฉ์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ ์ด๋Ÿฌํ•œ ํŒฉ์€ ์›๋ณธ์—์„œ ํ™•์ธ๋˜๋ฏ€๋กœ ๊ณ ์ •๋œ ๋ฒ„์ „์˜ ํŒฉ์„ ์ง€์ •ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์ด extractor(์€)๋Š” CodeQL ํŒฉ์— ์ €์žฅ๋œ ์ฝ”๋“œ ํŒŒ์ผ์—์„œ ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐ CLI์—์„œ ์‚ฌ์šฉํ•  ์–ธ์–ด๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ CodeQL ํŒฉ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ถ„์„ ์‚ฌ์šฉ์ž ์ง€์ •์„(๋ฅผ) ์ฐธ์กฐํ•˜์„ธ์š”.

์ฟผ๋ฆฌ ํ…Œ์ŠคํŠธ๊ฐ€ CodeQL ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์—์„œ ๊ตฌ์„ฑ๋˜๋Š” ๋ฐฉ์‹์„ ์‚ดํŽด๋ณด๋Š” ๊ฒƒ์ด ์œ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ ์–ธ์–ด์—๋Š” ์ฝ”๋“œ๋ฒ ์ด์Šค๋ฅผ ๋ถ„์„ํ•˜๊ธฐ ์œ„ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ฐ ์ฟผ๋ฆฌ๋ฅผ ํฌํ•จํ•˜๋Š” src ๋””๋ ‰ํ„ฐ๋ฆฌ ๋ฐ ql/<language>/ql/src(์ด)๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. src ๋””๋ ‰ํ„ฐ๋ฆฌ์™€ ํ•จ๊ป˜ ์ด๋Ÿฌํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ฐ ์ฟผ๋ฆฌ์— ๋Œ€ํ•œ ํ…Œ์ŠคํŠธ๊ฐ€ ํฌํ•จ๋œ test ๋””๋ ‰ํ„ฐ๋ฆฌ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฐ test ๋””๋ ‰ํ„ฐ๋ฆฌ๋Š” ๋‘ ๊ฐœ์˜ ํ•˜์œ„ ๋””๋ ‰ํ„ฐ๋ฆฌ๊ฐ€ ์žˆ๋Š” ํ…Œ์ŠคํŠธ CodeQL ํŒฉ์œผ๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.

  • query-tests src ๋””๋ ‰ํ„ฐ๋ฆฌ์— ์ €์žฅ๋œ ์ฟผ๋ฆฌ์— ๋Œ€ํ•œ ํ…Œ์ŠคํŠธ๊ฐ€ ํฌํ•จ๋œ ์ผ๋ จ์˜ ํ•˜์œ„ ๋””๋ ‰ํ„ฐ๋ฆฌ์ž…๋‹ˆ๋‹ค. ๊ฐ ํ•˜์œ„ ๋””๋ ‰ํ„ฐ๋ฆฌ์—๋Š” ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์™€ ํ…Œ์ŠคํŠธํ•  ์ฟผ๋ฆฌ๋ฅผ ์ง€์ •ํ•˜๋Š” QL ์ฐธ์กฐ ํŒŒ์ผ์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.
  • library-tests QL ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํŒŒ์ผ์— ๋Œ€ํ•œ ํ…Œ์ŠคํŠธ๋ฅผ ํฌํ•จํ•˜๋Š” ์ผ๋ จ์˜ ํ•˜์œ„ ๋””๋ ‰ํ„ฐ๋ฆฌ์ž…๋‹ˆ๋‹ค. ๊ฐ ํ•˜์œ„ ๋””๋ ‰ํ„ฐ๋ฆฌ์—๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์šฉ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋กœ ์ž‘์„ฑ๋œ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ๋ฐ ์ฟผ๋ฆฌ๊ฐ€ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

qlpack.yml ํŒŒ์ผ์„ ๋งŒ๋“  ํ›„์—๋Š” ๋ชจ๋“  ์ข…์†์„ฑ์ด ๋‹ค์šด๋กœ๋“œ๋˜์–ด CLI์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ํ™•์ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. qlpack.yml ํŒŒ์ผ๊ณผ ๋™์ผํ•œ ๋””๋ ‰ํ„ฐ๋ฆฌ์—์„œ ๋‹ค์Œ ๋ช…๋ น์„ ์‹คํ–‰ํ•˜์—ฌ ์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

codeql pack install

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ด ํŒฉ์—์„œ ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ๋ชจ๋“  ์ „์ด์  ์ข…์†์„ฑ์„ ์ง€์ •ํ•˜๋Š” codeql-pack.lock.yml ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด ํŒŒ์ผ์€ ์†Œ์Šค ๊ด€๋ฆฌ์— ์ฒดํฌ์ธ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ฟผ๋ฆฌ์šฉ ํ…Œ์ŠคํŠธ ํŒŒ์ผ ์„ค์ •

ํ…Œ์ŠคํŠธํ•˜๋ ค๋Š” ๊ฐ ์ฟผ๋ฆฌ์šฉ์œผ๋กœ ํ…Œ์ŠคํŠธ CodeQL ํŒฉ์— ํ•˜์œ„ ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ํ…Œ์ŠคํŠธ ๋ช…๋ น์„ ์‹คํ–‰ํ•˜๊ธฐ ์ „์— ํ•˜์œ„ ๋””๋ ‰ํ„ฐ๋ฆฌ์— ๋‹ค์Œ ํŒŒ์ผ์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

  • ํ…Œ์ŠคํŠธํ•  ์ฟผ๋ฆฌ์˜ ์œ„์น˜๋ฅผ ์ •์˜ํ•˜๋Š” ์ฟผ๋ฆฌ ์ฐธ์กฐ ํŒŒ์ผ(.qlref ํŒŒ์ผ)์ž…๋‹ˆ๋‹ค. ์œ„์น˜๋Š” ์ฟผ๋ฆฌ๊ฐ€ ํฌํ•จ๋œ CodeQL ํŒฉ์˜ ๋ฃจํŠธ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ •์˜๋ฉ๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ ํ…Œ์ŠคํŠธ ํŒฉ์˜ dependencies ๋ธ”๋ก์— ์ง€์ •๋œ CodeQL ํŒฉ์ž…๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์ฟผ๋ฆฌ ์ฐธ์กฐ ํŒŒ์ผ์„(๋ฅผ) ์ฐธ์กฐํ•˜์„ธ์š”.

    ํ…Œ์ŠคํŠธํ•˜๋ ค๋Š” ์ฟผ๋ฆฌ๊ฐ€ ํ…Œ์ŠคํŠธ ๋””๋ ‰ํ„ฐ๋ฆฌ์— ์ €์žฅ๋œ ๊ฒฝ์šฐ ์ฟผ๋ฆฌ ์ฐธ์กฐ ํŒŒ์ผ์„ ์ถ”๊ฐ€ํ•  ํ•„์š”๊ฐ€ ์—†์ง€๋งŒ, ์ผ๋ฐ˜์ ์œผ๋กœ ํ…Œ์ŠคํŠธ์™€ ๋ณ„๋„๋กœ ์ฟผ๋ฆฌ๋ฅผ ์ €์žฅํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ์œ ์ผํ•œ ์˜ˆ์™ธ๋Š” ๊ฒฝ๊ณ  ๋˜๋Š” ๊ฒฝ๋กœ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ์ฟผ๋ฆฌ์™€๋Š” ๋ณ„๋„๋กœ ํ…Œ์ŠคํŠธ ํŒฉ์— ์ €์žฅ๋˜๋Š” ๊ฒฝํ–ฅ์ด ์žˆ๋Š” QL ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์šฉ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ์ž…๋‹ˆ๋‹ค.

  • ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•  ์˜ˆ์ œ ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค. ์ฟผ๋ฆฌ๊ฐ€ ์‹๋ณ„ํ•˜๋„๋ก ์„ค๊ณ„๋œ ์ฝ”๋“œ์˜ ์˜ˆ์ œ๋ฅผ ํฌํ•จํ•˜๋Š” ํ•˜๋‚˜ ์ด์ƒ์˜ ํŒŒ์ผ๋กœ ๊ตฌ์„ฑ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ํ™•์žฅ๋ช…์ด .expected์ธ ํŒŒ์ผ์„ ๋งŒ๋“ค์–ด ์˜ˆ์ œ ์ฝ”๋“œ์šฉ ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•  ๋•Œ ์˜ˆ์ƒ๋˜๋Š” ๊ฒฐ๊ณผ๋ฅผ ์ •์˜ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ํ…Œ์ŠคํŠธ ๋ช…๋ น์„ ๊ทธ๋Œ€๋กœ ๋‘๊ณ  .expected ํŒŒ์ผ์„ ๋งŒ๋“ค ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฟผ๋ฆฌ๋ฅผ ๋งŒ๋“ค๊ณ  ํ…Œ์ŠคํŠธํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ ์ฃผ๋Š” ์˜ˆ์ œ๋Š”, ์•„๋ž˜ ์˜ˆ์ œ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

์ฐธ๊ณ  ํ•ญ๋ชฉ

.ql, .qlref, .expected ํŒŒ์ผ์€ ์ผ๊ด€๋œ ์ด๋ฆ„์ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  • ํ…Œ์ŠคํŠธ ๋ช…๋ น์—์„œ .ql ํŒŒ์ผ ์ž์ฒด๋ฅผ ์ง์ ‘ ์ง€์ •ํ•˜๋ ค๋ฉด ํ•ด๋‹น .expected ํŒŒ์ผ๊ณผ ๋™์ผํ•œ ๊ธฐ๋ณธ ์ด๋ฆ„์ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์ฟผ๋ฆฌ๊ฐ€ MyJavaQuery.ql์ธ ๊ฒฝ์šฐ ์˜ˆ์ƒ ๊ฒฐ๊ณผ ํŒŒ์ผ์€ MyJavaQuery.expected(์ด)๊ฐ€ ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ํ…Œ์ŠคํŠธ ๋ช…๋ น์—์„œ .qlref ํŒŒ์ผ์„ ์ง€์ •ํ•˜๋ ค๋ฉด, ํ•ด๋‹น .expected ํŒŒ์ผ๊ณผ ๋™์ผํ•œ ๊ธฐ๋ณธ ์ด๋ฆ„์ด ์žˆ์–ด์•ผ ํ•˜์ง€๋งŒ ์ฟผ๋ฆฌ ์ž์ฒด ์ด๋ฆ„์€ ๋‹ค๋ฅผ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์˜ˆ์ œ ์ฝ”๋“œ ํŒŒ์ผ์˜ ์ด๋ฆ„์€ ๋‹ค๋ฅธ ํ…Œ์ŠคํŠธ ํŒŒ์ผ๊ณผ ์ผ์น˜ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. .qlref (๋˜๋Š”.ql) ํŒŒ์ผ ์˜†์— ์žˆ๋Š” ๋ชจ๋“  ์˜ˆ์ œ ์ฝ”๋“œ ํŒŒ์ผ๊ณผ ํ•˜์œ„ ๋””๋ ‰ํ„ฐ๋ฆฌ์—์„œ ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๊ฐ„๋‹จํžˆ ํ•˜๊ธฐ ์œ„ํ•ด ์„œ๋กœ์˜ ์ƒ์œ„ ํ•ญ๋ชฉ์ธ ๋””๋ ‰ํ„ฐ๋ฆฌ์— ํ…Œ์ŠคํŠธ ํŒŒ์ผ์„ ์ €์žฅํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

codeql test run ์‹คํ–‰

CodeQL ์ฟผ๋ฆฌ ํ…Œ์ŠคํŠธ๋Š” ๋‹ค์Œ ๋ช…๋ น์„ ์‹คํ–‰ํ•˜์—ฌ ์‹ค์‹œ๋ฉ๋‹ˆ๋‹ค.

codeql test run <test|dir>

<test|dir> ์ธ์ˆ˜๋Š” ๋‹ค์Œ ์ค‘ ํ•˜๋‚˜ ์ด์ƒ์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • .ql ํŒŒ์ผ์— ๋Œ€ํ•œ ๊ฒฝ๋กœ์ž…๋‹ˆ๋‹ค.
  • .ql ํŒŒ์ผ์„ ์ฐธ์กฐํ•˜๋Š” .qlref ํŒŒ์ผ์˜ ๊ฒฝ๋กœ์ž…๋‹ˆ๋‹ค.
  • .ql ๋ฐ .qlref ํŒŒ์ผ์„ ์žฌ๊ท€์ ์œผ๋กœ ๊ฒ€์ƒ‰ํ•  ๋””๋ ‰ํ„ฐ๋ฆฌ ๊ฒฝ๋กœ์ž…๋‹ˆ๋‹ค.

๋‹ค์Œ์„ ์ง€์ •ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

  • --threads: ์„ ํƒ์ ์œผ๋กœ ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•  ๋•Œ ์‚ฌ์šฉํ•  ์Šค๋ ˆ๋“œ ์ˆ˜์ž…๋‹ˆ๋‹ค. ๊ธฐ๋ณธ ์˜ต์…˜์€ 1์ž…๋‹ˆ๋‹ค. ๋” ๋งŽ์€ ์Šค๋ ˆ๋“œ๋ฅผ ์ง€์ •ํ•˜์—ฌ ์ฟผ๋ฆฌ ์‹คํ–‰ ์†๋„๋ฅผ ๋†’์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์Šค๋ ˆ๋“œ ์ˆ˜๋ฅผ ๋…ผ๋ฆฌ ํ”„๋กœ์„ธ์„œ ์ˆ˜์™€ ์ผ์น˜์‹œํ‚ค๋ ค๋ฉด 0(์œผ)๋กœ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.

์ฟผ๋ฆฌ๋ฅผ ํ…Œ์ŠคํŠธํ•  ๋•Œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ์˜ต์…˜์— ๋Œ€ํ•œ ์ „์ฒด ๋‚ด์šฉ์€ ํ…Œ์ŠคํŠธ ์‹คํ–‰์„(๋ฅผ) ์ฐธ์กฐํ•˜์„ธ์š”.

์˜ˆ์‹œ

๋‹ค์Œ ์˜ˆ์ œ์—์„œ๋Š” Java ์ฝ”๋“œ์—์„œ ๋นˆ then ๋ธ”๋ก์ด ์žˆ๋Š” if ๋ฌธ์„ ๊ฒ€์ƒ‰ํ•˜๋Š” ์ฟผ๋ฆฌ์— ๋Œ€ํ•œ ํ…Œ์ŠคํŠธ๋ฅผ ์„ค์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ ์ค๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—๋Š” ์‚ฌ์šฉ์ž ์ง€์ • ์ฟผ๋ฆฌ ๋ฐ ํ•ด๋‹น ํ…Œ์ŠคํŠธ ํŒŒ์ผ์„ ์ถ”๊ฐ€ํ•˜์—ฌ CodeQL ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์˜ ์ฒดํฌ ์•„์›ƒ ์™ธ๋ถ€์— ์žˆ๋Š” CodeQL ํŒฉ์„ ๊ตฌ๋ถ„ํ•˜๋Š” ๋‹จ๊ณ„๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด CodeQL ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๊ฑฐ๋‚˜ ๋‹ค๋ฅธ ๋ถ„๊ธฐ๋ฅผ ์ฒดํฌ ์•„์›ƒํ•  ๊ฒฝ์šฐ ์‚ฌ์šฉ์ž ์ง€์ • ์ฟผ๋ฆฌ ๋ฐ ํ…Œ์ŠคํŠธ๋ฅผ ๋ฎ์–ด์“ฐ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ฟผ๋ฆฌ ๋ฐ ํ…Œ์ŠคํŠธ ํŒŒ์ผ ์ค€๋น„

  1. ์ฟผ๋ฆฌ๋ฅผ ๊ฐœ๋ฐœํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์Œ์˜ ๊ฐ„๋‹จํ•œ ์ฟผ๋ฆฌ๋Š” Java ์ฝ”๋“œ์—์„œ ๋นˆ then ๋ธ”๋ก์„ ์ฐพ์Šต๋‹ˆ๋‹ค.

    import java
    
    from IfStmt ifstmt
    where ifstmt.getThen() instanceof EmptyStmt
    select ifstmt, "This if statement has an empty then."
    
  2. ๋‹ค๋ฅธ ์‚ฌ์šฉ์ž ์ง€์ • ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋””๋ ‰ํ„ฐ๋ฆฌ์— EmptyThen.ql(์œผ)๋กœ ๋ช…๋ช…๋œ ํŒŒ์ผ์— ์ฟผ๋ฆฌ๋ฅผ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ: custom-queries/java/queries/EmptyThen.ql.

  3. ์‚ฌ์šฉ์ž ์ง€์ • ์ฟผ๋ฆฌ๋ฅผ CodeQL ํŒฉ์— ์•„์ง ์ถ”๊ฐ€ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ์ด์ œ CodeQL ํŒฉ์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์‚ฌ์šฉ์ž ์ง€์ • Java ์ฟผ๋ฆฌ๊ฐ€ custom-queries/java/queries์— ์ €์žฅ๋œ ๊ฒฝ์šฐ ๋‹ค์Œ ๋‚ด์šฉ์ด ํฌํ•จ๋œ qlpack.yml ํŒŒ์ผ์„ custom-queries/java/queries์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

    name: my-custom-queries
    dependencies:
      codeql/java-queries: "*"
    

    CodeQL ํŒฉ์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ "CodeQL ํŒฉ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ถ„์„ ์‚ฌ์šฉ์ž ์ง€์ •"์„(๋ฅผ) ์ฐธ์กฐํ•˜์„ธ์š”.

  4. ๋‹ค์Œ ๋‚ด์šฉ์ด ํฌํ•จ๋œ qlpack.yml ํŒŒ์ผ์„ custom-queries/java/tests์— ์ถ”๊ฐ€ํ•˜๊ณ  ์‚ฌ์šฉ์ž ์ง€์ • ์ฟผ๋ฆฌ์˜ CodeQL ํŒฉ์˜ ์ด๋ฆ„๊ณผ ์ผ์น˜ํ•˜๋„๋ก dependencies(์„)๋ฅผ ์—…๋ฐ์ดํŠธํ•˜์—ฌ Java ํ…Œ์ŠคํŠธ์šฉ CodeQL ํŒฉ์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

    ๋‹ค์Œ qlpack.yml ํŒŒ์ผ์€ 1.2.3๋ณด๋‹ค ํฌ๊ฑฐ๋‚˜ ๊ฐ™์€ ๋ฒ„์ „๊ณผ 2.0.0๋ณด๋‹ค ์ž‘์€ ๋ฒ„์ „์— my-github-user/my-query-tests๋”ฐ๋ผ ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค my-github-user/my-custom-queries . ๋˜ํ•œ CLI๋Š” ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๋งŒ๋“ค ๋•Œ Java extractor์„(๋ฅผ) ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค. ์ด tests: . ์ค„์€ --strict-test-discovery ์˜ต์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ์‹คํ–‰ํ•  ๋•Œ ํŒฉ์˜ ๋ชจ๋“  .ql ํŒŒ์ผ์„ ํ…Œ์ŠคํŠธ๋กœ codeql test run์‹คํ–‰ํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ ํ…Œ์ŠคํŠธ ํŒฉ์—๋Š” version ์†์„ฑ์ด ํฌํ•จ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์‹ค์ˆ˜๋กœ ๊ฒŒ์‹œ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

    name: my-github-user/my-query-tests
    dependencies:
      my-github-user/my-custom-queries: ^1.2.3
    extractor: java-kotlin
    tests: .
    
  5. ํ…Œ์ŠคํŠธ ๋””๋ ‰ํ„ฐ๋ฆฌ์˜ ๋ฃจํŠธ์—์„œ codeql pack install(์„)๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ด ํŒฉ์—์„œ ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ๋ชจ๋“  ์ „์ด์  ์ข…์†์„ฑ์„ ์ง€์ •ํ•˜๋Š” codeql-pack.lock.yml ํŒŒ์ผ์ด ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.

  6. Java ํ…Œ์ŠคํŠธ ํŒฉ ๋‚ด์—์„œ EmptyThen.ql(์™€)๊ณผ ์—ฐ๊ฒฐ๋œ ํ…Œ์ŠคํŠธ ํŒŒ์ผ์„ ํฌํ•จํ•  ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ์˜ˆ: custom-queries/java/tests/EmptyThen.

  7. ์ƒˆ ๋””๋ ‰ํ„ฐ๋ฆฌ์—์„œ EmptyThen.qlref(์„)๋ฅผ ๋งŒ๋“ค์–ด EmptyThen.ql์˜ ์œ„์น˜๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. ๋””๋ ‰ํ„ฐ๋ฆฌ์˜ ๊ฒฝ๋กœ๋Š” ์ฟผ๋ฆฌ๊ฐ€ ํฌํ•จ๋œ CodeQL ํŒฉ์˜ ๋ฃจํŠธ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ง€์ •๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ์ฟผ๋ฆฌ๋Š” my-query-tests์— ๋Œ€ํ•œ ์ข…์†์„ฑ์œผ๋กœ ์„ ์–ธ๋œ my-custom-queries์ด๋ผ๋Š” CodeQL ํŒฉ์˜ ์ตœ์ƒ์œ„ ๋””๋ ‰ํ„ฐ๋ฆฌ์— ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ EmptyThen.qlref(์€) ๋‹จ์ˆœํžˆ EmptyThen.ql(์„)๋ฅผ ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  8. ์ฝ”๋“œ ์กฐ๊ฐ์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ๋‹ค์Œ Java ์ฝ”๋“œ๋Š” ์„ธ ๋ฒˆ์งธ ์ค„์— ๋นˆ if ๋ฌธ์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. custom-queries/java/tests/EmptyThen/Test.java์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.

    class Test {
      public void problem(String arg) {
        if (arg.isEmpty())
          ;
        {
          System.out.println("Empty argument");
        }
      }
    
      public void good(String arg) {
        if (arg.isEmpty()) {
          System.out.println("Empty argument");
        }
      }
    }
    

ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•˜๋ ค๋ฉด custom-queries ๋””๋ ‰ํ„ฐ๋ฆฌ๋กœ ์ด๋™ํ•˜์—ฌ codeql test run java/tests/EmptyThen(์„)๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

ํ…Œ์ŠคํŠธ๊ฐ€ ์‹คํ–‰๋˜๋ฉด ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

  1. EmptyThen ๋””๋ ‰ํ„ฐ๋ฆฌ์—์„œ ํ…Œ์ŠคํŠธ ํ•˜๋‚˜๋ฅผ ์ฐพ์Šต๋‹ˆ๋‹ค.

  2. EmptyThen ๋””๋ ‰ํ„ฐ๋ฆฌ์— ์ €์žฅ๋œ .java ํŒŒ์ผ์—์„œ CodeQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์ถ”์ถœํ•ฉ๋‹ˆ๋‹ค.

  3. EmptyThen.qlref ํŒŒ์ผ์—์„œ ์ฐธ์กฐํ•˜๋Š” ์ฟผ๋ฆฌ๋ฅผ ์ปดํŒŒ์ผํ•ฉ๋‹ˆ๋‹ค.

    ์ด ๋‹จ๊ณ„๊ฐ€ ์‹คํŒจํ•˜๋ฉด CLI์—์„œ ์‚ฌ์šฉ์ž ์ง€์ • CodeQL ํŒฉ์„ ์ฐพ์ง€ ๋ชปํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋ช…๋ น์„ ๋‹ค์‹œ ์‹คํ–‰ํ•˜๊ณ  ์‚ฌ์šฉ์ž ์ง€์ • CodeQL ํŒฉ์˜ ์œ„์น˜๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

    codeql test run --search-path=java java/tests/EmptyThen

    ๊ตฌ์„ฑ์˜ ์ผ๋ถ€๋กœ ๊ฒ€์ƒ‰ ๊ฒฝ๋กœ๋ฅผ ์ €์žฅํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ CodeQL ๊ตฌ์„ฑ ํŒŒ์ผ์—์„œ ๋ช…๋ น ์˜ต์…˜ ์ง€์ •ํ•˜๊ธฐ์„(๋ฅผ) ์ฐธ์กฐํ•˜์„ธ์š”.

  4. ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜๊ณ  EmptyThen.actual ๊ฒฐ๊ณผ ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜์—ฌ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

  5. .actual ๊ฒฐ๊ณผ ํŒŒ์ผ๊ณผ ๋น„๊ตํ•  EmptyThen.expected ํŒŒ์ผ์„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

  6. ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๊ณ ํ•ฉ๋‹ˆ๋‹ค. 0 tests passed; 1 tests failed:์˜ ๊ฒฝ์šฐ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ์ฟผ๋ฆฌ์˜ ์˜ˆ์ƒ ๊ฒฐ๊ณผ๊ฐ€ ํฌํ•จ๋œ ํŒŒ์ผ์„ ์•„์ง ์ถ”๊ฐ€ํ•˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— ํ…Œ์ŠคํŠธ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.

์ฟผ๋ฆฌ ํ…Œ์ŠคํŠธ ์ถœ๋ ฅ ๋ณด๊ธฐ

CodeQL์€(๋Š”) EmptyThen ๋””๋ ‰ํ„ฐ๋ฆฌ์— ๋‹ค์Œ ํŒŒ์ผ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

  • EmptyThen.actual, ์ฟผ๋ฆฌ์—์„œ ์ƒ์„ฑ๋œ ์‹ค์ œ ๊ฒฐ๊ณผ๋ฅผ ํฌํ•จํ•˜๋Š” ํŒŒ์ผ์ž…๋‹ˆ๋‹ค.
  • EmptyThen.testproj, VS Code์— ๋กœ๋“œํ•˜๊ณ  ์‹คํŒจํ•œ ํ…Œ์ŠคํŠธ๋ฅผ ๋””๋ฒ„๊ทธํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์ž…๋‹ˆ๋‹ค. ํ…Œ์ŠคํŠธ๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ์™„๋ฃŒ๋˜๋ฉด ์ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ํ•˜์šฐ์Šคํ‚คํ•‘ ๋‹จ๊ณ„์—์„œ ์‚ญ์ œ๋ฉ๋‹ˆ๋‹ค. --keep-databases ์˜ต์…˜์œผ๋กœ test run(์„)๋ฅผ ์‹คํ–‰ํ•˜์—ฌ ์ด ๋‹จ๊ณ„๋ฅผ ์žฌ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ๊ฒฝ์šฐ ์˜ˆ์ƒ๋œ ์˜ค๋ฅ˜๋ฅผ ์‰ฝ๊ฒŒ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. EmptyThen.actual ํŒŒ์ผ์„ ์—ด๋ฉด ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


| Test.java:3:5:3:22 | stmt | This if statement has an empty then. |

์ด ํŒŒ์ผ์—๋Š” ์ฟผ๋ฆฌ๊ฐ€ ์ถœ๋ ฅํ•˜๋Š” select ์ ˆ์˜ ๊ฐ ๋ถ€๋ถ„์— ๋Œ€ํ•œ ๋ณ„๋„์˜ ์—ด๊ณผ ํ•จ๊ป˜ ๊ฒฐ๊ณผ ์œ„์น˜์— ๋Œ€ํ•œ ์—ด์ด ์žˆ๋Š” ํ…Œ์ด๋ธ”์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ์ƒ๋œ ๊ฒฐ๊ณผ์ด๋ฏ€๋กœ ํŒŒ์ผ ํ™•์žฅ์ž๋ฅผ ์—…๋ฐ์ดํŠธํ•˜์—ฌ ์ด ํ…Œ์ŠคํŠธ(EmptyThen.expected)์— ๋Œ€ํ•œ ์˜ˆ์ƒ ๊ฒฐ๊ณผ๋กœ ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ง€๊ธˆ ํ…Œ์ŠคํŠธ๋ฅผ ๋‹ค์‹œ ์‹คํ–‰ํ•˜๋ฉด ์ถœ๋ ฅ์€ ๋น„์Šทํ•˜์ง€๋งŒ All 1 tests passed.(์„)๋ฅผ ๋ณด๊ณ ํ•˜์—ฌ ์™„๋ฃŒ๋ฉ๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด ์ฟผ๋ฆฌ์˜ ๊ฒฐ๊ณผ๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด ์ฟผ๋ฆฌ์— ๋Œ€ํ•œ select ๋ฌธ์„ ์ˆ˜์ •ํ•  ๊ฒฝ์šฐ, ํ…Œ์ŠคํŠธ๊ฐ€ ์‹คํŒจํ•ฉ๋‹ˆ๋‹ค. ์‹คํŒจํ•œ ๊ฒฐ๊ณผ์˜ ๊ฒฝ์šฐ CLI ์ถœ๋ ฅ์—๋Š” EmptyThen.expected ๋ฐ EmptyThen.actual ํŒŒ์ผ์˜ ํ†ตํ•ฉ๋œ ์ฐจ์ด๊ฐ€ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. ์ด ์ •๋ณด๋Š” ๊ฐ„๋‹จํ•œ ํ…Œ์ŠคํŠธ ์˜ค๋ฅ˜๋ฅผ ๋””๋ฒ„๊ทธํ•˜๊ธฐ์— ์ถฉ๋ถ„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋””๋ฒ„๊ทธํ•˜๊ธฐ ์–ด๋ ค์šด ์˜ค๋ฅ˜์˜ ๊ฒฝ์šฐ, EmptyThen.testproj(์„)๋ฅผ VS Code์šฉ CodeQL(์œผ)๋กœ ๊ฐ€์ ธ์™€ Test.java์˜ˆ์ œ ์ฝ”๋“œ์—์„œ EmptyThen.ql(์„)๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ CodeQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ด€๋ฆฌ์„(๋ฅผ) ์ฐธ์กฐํ•˜์„ธ์š”.

์ถ”๊ฐ€ ์ฐธ๊ณ  ์ž๋ฃŒ