Compare commits

...

3 Commits

Author SHA1 Message Date
88519283e1 added programs 2025-04-30 01:50:13 +09:00
6acb05157f added appendix 2025-04-30 01:01:49 +09:00
d8ae49b00d wrote most of report 2025-04-27 14:34:55 +09:00
34 changed files with 423 additions and 82 deletions

BIN
assets/prog1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

BIN
assets/prog2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

BIN
assets/prog3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

BIN
assets/prog4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

BIN
assets/prog5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

View File

@@ -1,18 +1,18 @@
doc_class: nitreport
title: Insert Title Here
title: 第3回課題
author:
name: 高専 太郎
student_id: 0000-01
name: 柴田 健琉
student_id: 15(2年生)
date:
year: 令和7年
month: aa
day: bb
month: 04
day: 30
school_name: abc高専
department: 一般
subject: 〇〇概論
professor: □□教員
school_name: 岐阜工業高等専門学校
department: 電子制御工学
subject: 情報処理I
professor: 岡崎 憲一
page_config:
include_cover_page: true
@@ -21,6 +21,11 @@ page_config:
show_compiled_time: true
sections:
- { path: 'section/introduction.tex', newpg: true }
- { path: 'md-out/test.tex', newpg: false }
- { path: 'section/introduction.tex', newpg: false }
- { path: 'section/syntax.tex', newpg: true }
- { path: 'section/prog1.tex', newpg: true }
- { path: 'section/prog2.tex', newpg: true }
- { path: 'section/prog3.tex', newpg: true }
- { path: 'section/prog4.tex', newpg: true }
- { path: 'section/prog5.tex', newpg: true }
- { path: 'section/appendix.tex', newpg: true }

49
main.tex Normal file
View File

@@ -0,0 +1,49 @@
\documentclass{class/nitreport}
\reporttitle{第3回課題}
\reportauthor{柴田 健琉}
\studentid{15(2年生)}
\reportdate{令和7年}{04月}{30日}
\schoolname{岐阜工業高等専門学校}
\department{電子制御工学科}
\subject{情報処理I}
\professor{岡崎 憲一}
\usepackage{ascmac}
\pagenumbering{roman}
\begin{document}
\coverpage
\tableofcontents
\newpage
\pagenumbering{arabic}
\input{section/introduction.tex}
\input{section/syntax.tex}
\newpage
\input{section/prog1.tex}
\newpage
\input{section/prog2.tex}
\newpage
\input{section/prog3.tex}
\newpage
\input{section/prog4.tex}
\newpage
\input{section/prog5.tex}
\newpage
\input{section/appendix.tex}
\newpage
\printbibliography
\compiledTime
\end{document}

BIN
output/main-opt-final.pdf Normal file

Binary file not shown.

BIN
output/main.pdf Normal file

Binary file not shown.

9
programs/prog1/info.json Normal file
View File

@@ -0,0 +1,9 @@
{
"name": "演習1ー5",
"description": "プロンプトから読み込んだ整数値に13を加えた値を表示するプログラム。",
"output": {
"type": "screenshot",
"content": "./assets/prog1.png"
},
"note": ""
}

BIN
programs/prog1/main Executable file

Binary file not shown.

12
programs/prog1/main.c Normal file
View File

@@ -0,0 +1,12 @@
#include <stdio.h>
int main(void) {
int x = 0;
printf("Input integer: x = ");
scanf("%d", &x);
printf("Result: x + 13 = %d\n", x + 13);
return 0;
}

9
programs/prog2/info.json Normal file
View File

@@ -0,0 +1,9 @@
{
"name": "演習1ー6",
"description": "プロンプトから読み込んだ整数値から7を減じた値を表示するプログラム。",
"output": {
"type": "screenshot",
"content": "./assets/prog2.png"
},
"note": ""
}

BIN
programs/prog2/main Executable file

Binary file not shown.

12
programs/prog2/main.c Normal file
View File

@@ -0,0 +1,12 @@
#include <stdio.h>
int main(void) {
int x = 0;
printf("Input integer: x = ");
scanf("%d", &x);
printf("Result: x - 7 = %d\n", x - 7);
return 0;
}

9
programs/prog3/info.json Normal file
View File

@@ -0,0 +1,9 @@
{
"name": "演習1ー8",
"description": "プロンプトから読み込んだ2つの整数値の積を表示するプログラム。",
"output": {
"type": "screenshot",
"content": "./assets/prog3.png"
},
"note": ""
}

BIN
programs/prog3/main Executable file

Binary file not shown.

16
programs/prog3/main.c Normal file
View File

@@ -0,0 +1,16 @@
#include <stdio.h>
int main(void) {
int n1;
int n2;
printf("Input two integers.\n");
printf("Integer n1: ");
scanf("%d", &n1);
printf("Integer n2: ");
scanf("%d", &n2);
printf("The product of two integers is %d.", n1 * n2);
return 0;
}

9
programs/prog4/info.json Normal file
View File

@@ -0,0 +1,9 @@
{
"name": "演習1ー9",
"description": "プロンプトから読み込んだ3つの整数値の和を表示するプログラム。",
"output": {
"type": "screenshot",
"content": "./assets/prog4.png"
},
"note": ""
}

BIN
programs/prog4/main Executable file

Binary file not shown.

19
programs/prog4/main.c Normal file
View File

@@ -0,0 +1,19 @@
#include <stdio.h>
int main(void) {
int n1;
int n2;
int n3;
printf("Input three integers.\n");
printf("Integer n1: ");
scanf("%d", &n1);
printf("Integer n2: ");
scanf("%d", &n2);
printf("Integer n3: ");
scanf("%d", &n3);
printf("The sum of three integers is %d.", n1 + n2 + n3);
return 0;
}

9
programs/prog5/info.json Normal file
View File

@@ -0,0 +1,9 @@
{
"name": "考察List 1-11",
"description": "List 1-11 にて、入力に3.14や0.5などの小数を入力すると出力はどうなるか。",
"output": {
"type": "screenshot",
"content": "./assets/prog5.png"
},
"note": "入力した全ての小数が繰り下げられている。\\\\texttt{\\%d}は整数しか表示できず、小数の場合は小数部を切り捨て、整数部のみ表示している。"
}

BIN
programs/prog5/main Executable file

Binary file not shown.

12
programs/prog5/main.c Normal file
View File

@@ -0,0 +1,12 @@
#include <stdio.h>
int main(void) {
int no;
printf("Input an integer: ");
scanf("%d", &no);
printf("You inputed %d.\n", no);
return 0;
}

View File

@@ -1,9 +1,41 @@
@online{example,
title = {Example Entry},
author = {Inc., Example},
organization = {Example, Inc.},
url = {https://www.example.com},
year = {1970},
month = {01},
urldate = {1970-01-01}
@online{cppref_scanf,
title = {scanf, fscanf, sscanf, scanf\_s, fscanf\_s, sscanf\_s},
author = {Eendy and P12bot and P12 and Cubbi and Newatthis and Himanshujha199640 and LittleFlower and D41D8CD98F and Mission, Space},
url = {https://en.cppreference.com/w/c/io/fscanf},
year = {2022},
month = {07},
urldate = {2025-04-24}
}
@online{cppref_stdio,
title = {Standard library header <stdio.h>},
author = {Mission, Space},
url = {https://en.cppreference.com/w/c/header/stdio},
year = {2025},
month = {02},
urldate = {2025-04-27}
}
@misc{lowlevel_canary,
title = {what ever happend to buffer overflows?},
author = {Level, Low},
url = {https://www.youtube.com/watch?v=z6gdQt8mjn4},
year = {2023},
month = {03},
urldate = {2025-04-27}
}
@misc{lowlevel_str,
title = {why do hackers love strings?},
author = {Level, Low},
url = {https://www.youtube.com/watch?v=fjMrDDj47E8},
year = {2022},
month = {11},
urldate = {2025-04-27}
}
@online{cve_sudo,
title = {CVE Record: CVE-2021-3156},
author = {Program, CVE},
organization = {CVE Program},
url = {https://www.cve.org/CVERecord?id=CVE-2021-3156},
year = {2024},
month = {09},
urldate = {2025-04-30}
}

View File

@@ -50,7 +50,7 @@ function writeSection () {
local x=0
local res=""
[[ $note == "\n\nnull" ]] && note=""
[[ $note == "\n\nnull" || $note == "\n\n" ]] && note=""
res+="\\section{$sectionName}\n\n$description\n\n\\subsection{コードリスティング}\n\n"
@@ -64,6 +64,8 @@ function writeSection () {
x=$(($x+1))
done
res+="\n\\subsection{実行結果}\n"
if [[ $outType == "screenshot" ]]; then
res+="\n\\\\begin{center}\n \\includegraphics[width=\\\\textwidth]{$outContent}\n\\\\end{center}"
elif [[ $outType == "text" ]]; then

89
section/appendix.tex Normal file
View File

@@ -0,0 +1,89 @@
\appendix
\section{付録}
\subsection{Code Hardening - バッファーオーバーフロー対策 \texttt{scanf}}
{\Large C言語は比較的自由な言語だ。しかし自由には責任が伴う。}
\vspace{0.25cm}
初学者からベテランCプログラマーが誰でも1度はやらかしてしまう間違いとして文字列の読み込みによるバッファーオーバーフローがある。
バッファーオーバーフローは静的・動的に割り当てられたメモリー領域外に書き込むことで発生する。
今回の演習課題は整数値を読み込んだが、バッファーオーバフローは起こらないが、整数値オーバーフロー・アンダーフローという別の問題が起こる。
しかし、このバグによる影響は比較的小さい。
なぜなら、これらの整数は関数のスタック上の変数として決まったサイズでメモリーに割り当てられており、領域外への値の書き込みがないからである。
しかし、ユーザーが入力する文字列となると話が違ってくる。
バッファーに過剰な量のデータが流入することバッファーオーバーフローが起こり、最悪の場合、バッファー外のデータを侵食・書き換えてしまい、プログラムが誤動作する。\cite{lowlevel_str}
静的に割り当てられた変数のバッファーオーバーフローは対処が容易であるが、実行するまでサイズが不明な場合が多い動的に割り当てられた変数の対策はその限りではない。
文字列・配列への範囲外読み書きはユーザーやネットワーク要求からの入力を扱う際にはより注意する必要がある。
開発者がすべてのユーザーが指示に従うと思い込むのは、はっきり言って\textbf{愚か}である。
プログラムはすべてメモリ安全性を第一に考えて書かれるべきである。
実際、このような脆弱性がシステムの全権を取得できてしまう程の問題を簡単なエラーによって引き起こされる場合がある。
例えば、「CVE-2021-3156」ではLinux等での非管理者ユーザーが管理者としてファイル編集できるようにする「sudoedit」コマンドでは、
配列のサイズが1つずれただけでバッファーオーバーフローを発生させ、認証なしで管理者権限が付与されてしまうバグが存在した。\cite{cve_sudo}
PythonやJavaなどの多くの高級言語は配列のサイズを超える場所への値の代入はエラーとなりコンパイル時やプログラム実行中に停止するように設計されている。
しかしC言語はそのような設計はプログラム実行中には施されていない。\texttt{-Wall}フラグを使用しても警告を出すだけで止めることはない。
\footnote{gccなど最近のコンパイラでコンパイルされたプログラムはスタックカナリアと呼ばれる一昔の炭鉱夫が一酸化炭素検出のために使われた鳥のカナリアの様にバッファーオーバーフローなどによって関数スタックが破壊された際にプログラムを強制終了させるコードを追加する機能が常に有効化されている物が存在する。なおこの機能はヒープ(動的確保されたメモリ領域)には適応されない。\cite{lowlevel_canary}}
高級言語の文字列は本体の文字列と共にその長さが記録されているが、C言語はその長さは記録されず、代わりに終端文字が文字列の終わりを示めす。
\texttt{scanf}\texttt{gets}は終端文字を検出するまで読み込みを続ける。
裏を返せば、終端文字を見つける前にバッファーが溢れているときでも、範囲外への書き込みを続けてしまうということにも繋がる。
次の例を考える:企業のシステムにて、ユーザーがパスワード(文字列)を入力し、正しければ社員データベースを操作するサブルーチーンに変移する。
パスワードの入力を司る処理とパスワードを照合する処理は個別にサブルーチーンがあるものとする。
ユーザーが入力したパスワードは動的に確保した64バイトのバッファー領域に書き込まれる。
\newpage
\defaultlistingstyle
\begin{lstlisting}[language=C,title={対策されていないシステムの例}]
#include <stdio.h>
#include <stdlib.h>
#define PASSLEN 65
void databaseManagement();
int checkPassword(char* passwd) {
char passwd[PASSLEN];
scanf("%s", passwd);
return isCorrectPassword(passwd);
}
int main(void) {
printf("Database Login\nPassword: ");
if (checkPassword())
databaseManagement();
return 0;
}
\end{lstlisting}
この時、システムを悪用したいと企てるハッカーが65バイト以上の文字列を渡し、うまくバッファーオーバーフローを引き起こさせると、パスワードの入力を司るサブルーチーンの戻りアドレスが書き換えられ、照合サブルーチーンを介さずに直接データベース管理サブルーチーンを実行させる。
\texttt{scanf}関数での対策はいたってシンプルである:書式を\texttt{"\%<バッファーサイズ - 1>s"}に変更するだけである。
\footnote{この\texttt{-1}で終端文字が入るスペースを残す。}
これによって、読み出す文字数を制限し、バッファーオーバーフローを防ぐことができる。
もう一つの方法はC11規格から追加された\texttt{scanf\_s}関数を代わりに使用することである。
\texttt{scanf\_s}関数はオリジナルの\texttt{scanf}関数に新たにバッファーのサイズを受け付る引数を最後尾に追加し、エラーチェックをより厳密にしたもので、
これにより前述の方法と併用しつつ、明示的にバッファーサイズを指定することができる。\cite{cppref_scanf}
\defaultlistingstyle
\begin{lstlisting}[language=C,title={\texttt{scanf}関数の対策例}]
// scanf("%s", passwd);
scanf("64%s", passwd);
passwd[PASSLEN-1] = '\0'; // 終端文字の存在を保証する
// C11規格以降のみ
scanf_s("64%s", passwd, PASSLEN);
\end{lstlisting}

View File

@@ -1,67 +1,12 @@
\section{はじめに}
Start Writing!
\subsection{実行環境}
Use lualatex + biber to compile.
Test Bib\cite{example}
いろはにほへと ちりぬるを
{\gtfamily \sffamily \LaTeX で自由な組版を。}
{\gtfamily \sffamily Write freely with \LaTeX{}.}
{\ttfamily LaTeX shall be free forever!}
\defaultlistingstyle
\begin{lstlisting}[language=C, caption=Basic Hello World]
#include <stdlib.h>
int square(int n) {
return n*n;
}
int main(int argc, char** argv) {
char* msg = "Hello World";
int x = 3;
int y = square(x);
printf("%s\n", msg);
printf("f(x) = x^2; x: %d, y: %d\n", x, y);
return 0;
}
\end{lstlisting}
\begin{displaymath}
\int_{a}^{b} f(x) \,dx = F(b)-F(a)
\end{displaymath}
この課題のプログラムは以下の環境で動作することが確認されている:
\begin{itemize}
\item C
\item Python
\item Javascript
\item Rust
\item Haskell
\item OS: Arch Linux
\item CPU アーキテクチャ: \texttt{x86\_64}
\item C コンパイラ: \texttt{gcc (GCC) 14.2.1 20250207}
\item C コンパイラフラグ: \texttt{-Wall <ソースコード名> -o <プログラム名>}
\end{itemize}
\begin{enumerate}
\item lualatex <filename>.tex
\item biber <filename>
\item lualatex <filename>.tex
\item lualatex <filename>.tex
\end{enumerate}
\newpage
\section{Section}
section
\subsection{Sub Section}
sub section
\paragraph{Paragraph}
paragraph

13
section/prog1.tex Normal file
View File

@@ -0,0 +1,13 @@
\section{演習1ー5}
プロンプトから読み込んだ整数値に13を加えた値を表示するプログラム。
\subsection{コードリスティング}
\defaultlistingstyle
\lstinputlisting[language=C,title={演習1ー5}]{../programs/prog1/main.c}
\subsection{実行結果}
\begin{center}
\includegraphics[width=\textwidth]{./assets/prog1.png}
\end{center}

13
section/prog2.tex Normal file
View File

@@ -0,0 +1,13 @@
\section{演習1ー6}
プロンプトから読み込んだ整数値から7を減じた値を表示するプログラム。
\subsection{コードリスティング}
\defaultlistingstyle
\lstinputlisting[language=C,title={演習1ー6}]{../programs/prog2/main.c}
\subsection{実行結果}
\begin{center}
\includegraphics[width=\textwidth]{./assets/prog2.png}
\end{center}

13
section/prog3.tex Normal file
View File

@@ -0,0 +1,13 @@
\section{演習1ー8}
プロンプトから読み込んだ2つの整数値の積を表示するプログラム。
\subsection{コードリスティング}
\lstinputlisting[language=C,title={演習1ー8}]{../programs/prog3/main.c}
\subsection{実行結果}
\begin{center}
\includegraphics[width=\textwidth]{./assets/prog3.png}
\end{center}

13
section/prog4.tex Normal file
View File

@@ -0,0 +1,13 @@
\section{演習1ー9}
プロンプトから読み込んだ3つの整数値の和を表示するプログラム。
\subsection{コードリスティング}
\lstinputlisting[language=C,title={演習1ー9}]{../programs/prog4/main.c}
\subsection{実行結果}
\begin{center}
\includegraphics[width=\textwidth]{./assets/prog4.png}
\end{center}

19
section/prog5.tex Normal file
View File

@@ -0,0 +1,19 @@
\section{考察List 1-11}
List 1-11 にて、入力に3.14や0.5などの小数を入力すると出力はどうなるか。
\subsection{コードリスティング}
\lstinputlisting[language=C,title={考察List 1-11}]{../programs/prog5/main.c}
\subsection{実行結果}
\begin{center}
\includegraphics[width=\textwidth]{./assets/prog5.png}
\end{center}
\subsection{考察}
入力した全ての小数が繰り下げられている。
\texttt{\%d}は整数しか表示できず、小数の場合は小数部を切り捨て、整数部のみ表示している。
小数を表示したい場合は\texttt{printf}関数と\texttt{scanf}関数両方の書式を\texttt{\%f}にする必要がある。

32
section/syntax.tex Normal file
View File

@@ -0,0 +1,32 @@
\section{今回の構文}
\subsection{\texttt{scanf}関数}
\texttt{scanf}関数は標準入力から文字列を読み取り、指定された書式に沿って解釈し、解釈結果の値を指定された場所に保存する。
ここでいう場所とは変数のアドレスのことである。
書式は\texttt{printf}関数と同じものである。\cite{cppref_scanf}
\defaultlistingstyle
\begin{lstlisting}[language=C,title={\texttt{scanf}関数}]
scanf("<書式>", <変数1へのアドレス>, <変数2へのアドレス>, ...);
\end{lstlisting}
\begin{itembox}[l]{\textrm{コラム:標準入出力関数の戻り値}}
標準入出力関数には\texttt{void}型を返す関数はほとんど定義されていない。
\vspace{0.25cm}
\begin{center}
表1主な標準入出力関数の戻り値\cite{cppref_stdio}
\vspace{0.125cm}
\begin{tabular}{|ccl|}
\hline
関数 && \multicolumn{1}{c|}{概要} \\ \hline \hline
\texttt{scanf}& \texttt{int} & 正常に読み込まれた変数の数、0または\texttt{EOF}定数はエラーとなる \\ \hline
\texttt{printf}& \texttt{int} & \vtop{\hbox{\strut バッファーやストリームに書き込まれた文字の数、}\hbox{\strut 負の値はエラーとなる}} \\ \hline
\vtop{\hbox{\strut \texttt{setbuf, rewind,}} \hbox{\strut \texttt{clearerr, perror}}} & \texttt{void} & \vtop{\hbox{\strut これらの関数のみ値を返さない、}\hbox{\strut エラーになり得る処理ではないから}} \\ \hline
\end{tabular}
\end{center}
\end{itembox}