-
Notifications
You must be signed in to change notification settings - Fork 165
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
#780 でのCNativeW の初期状態での仕様を取り消して、 #948 の不具合を修正する #949
#780 でのCNativeW の初期状態での仕様を取り消して、 #948 の不具合を修正する #949
Conversation
sakura_core/mem/CMemory.cpp
Outdated
{ | ||
assert(m_nRawLen <= m_nDataBufSize-2); | ||
m_nRawLen = nLength; | ||
assert(m_nRawLen <= m_nDataBufSize-2); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
389行目と387行目の違いはなんでしょう?
この話も別件でよいです。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
388 行目を実行する前と後で両方とも成立するか確認しています。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
コメント足しました
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ここ、本当はこういうことだと思います。
if (m_nDataBufSize - 2 <= nLength) throw std::out_of_range("invalid arg");
if (m_nDataBufSize - 2 <= m_nRawLen) throw std::runtime_error("invalid state");
m_nRawLen = nLength;
コード記述上、代入してからチェックしてるので同じ書きっぷりのassertですが、
実態は引数チェックとメンバ変数の状態チェックだと思うんです。
変更後のコードに新しいコメント付けましたが、コードにコメント付けちゃうと「めんどいから後回し!」の大義名分を失うような気がしています。
sakura_core/mem/CMemory.cpp
Outdated
m_pRawData[m_nRawLen+1]=0; //終端'\0'を2つ付加する('\0''\0'==L'\0')。 | ||
if (m_nDataBufSize > 0) | ||
{ | ||
assert(m_nRawLen <= m_nDataBufSize-2); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
メモ:これはClear関数呼出の前提条件を外すための内部仕様変更。
変更前:利用中サイズが確保済みサイズ未満であればクラッシュ。
変更後:確保済みサイズが0より大きい場合、利用中サイズが確保済みサイズ未満であればクラッシュ。
sakura_core/mem/CMemory.cpp
Outdated
assert(m_nRawLen <= m_nDataBufSize-2); | ||
m_pRawData[m_nRawLen ]=0; | ||
m_pRawData[m_nRawLen+1]=0; //終端'\0'を2つ付加する('\0''\0'==L'\0')。 | ||
if (m_nDataBufSize > 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
この条件だと「(メモリ確保状態に関係なく)確保済みサイズが0より大きい場合」と読めます。
個人的な感覚では、if (m_pRawData && m_nDataBufSize)
が適切な条件だと思います。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
チェックを足しました。
sakura_core/mem/CMemory.cpp
Outdated
{ | ||
assert(m_nRawLen <= m_nDataBufSize-2); // m_nRawLen を変更する前に必要な条件が成立しているか確認する | ||
m_nRawLen = nLength; | ||
assert(m_nRawLen <= m_nDataBufSize-2); // m_nRawLen を変更した後も必要な条件が成立しているか確認する |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
「既存コードそのままインデントしただけなんで、細かいツッコミは勘弁してください」ならassert条件の精査は要らないと思っています。コメント足してしまうと、中身を理解した上でこれでおっけー、という意味になっちゃうような気がします。別件でいいと思っていたassert条件の精査を、いまやんないといけなくなる気がします。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
やらなくていいかどうかは置いておいて、ロジック自体は簡単です。
m_nRawLen が実際のデータサイズで、それに 終端'\0'を2つ付加しているので
その分の 2 を考慮してサイズが OK かチェックしています。
まあ -2
は左辺に持ってきたほうがいいかもしれませんが。
sakura/sakura_core/mem/CMemory.cpp
Lines 104 to 107 in 3d9d418
memcpy( &m_pRawData[m_nRawLen], pData, nDataLen ); | |
m_nRawLen += nDataLen; | |
m_pRawData[m_nRawLen] = '\0'; | |
m_pRawData[m_nRawLen+1] = '\0'; //終端'\0'を2つ付加する('\0''\0'==L'\0')。 2007.08.13 kobake 追加 |
sakura_core/mem/CMemory.cpp
Outdated
assert(m_nRawLen <= m_nDataBufSize-2); | ||
m_nRawLen = nLength; | ||
assert(m_nRawLen <= m_nDataBufSize-2); | ||
m_pRawData[m_nRawLen ]=0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
えいやっ!でapproveするタイミングを逸したので、
あらためて元のコードをよく見てみます。
PRの内容は、既に修正目的を果たしているように思うんですが、
メソッドの元々の目的と修正目的を合わせてみたときに「適切な変更かどうか」に疑問があります。
このメソッドでやりたいことは次の2つです。
- 387行目
利用中サイズ
に引数「新しいサイズ」
を代入する。 - 389行目
確保済みバッファ
の引数「新しいサイズ」
の位置に文字列終端を書き込む。
他の3行はオマケです。エロい人にはそれが分からんのです・・・が、
386行目のassertが原因でメモリ確保前にClear()してはならないという仕様
になっていました。
メモリ確保前はClear()できないとすると、Clear()の前に毎回チェックが必要になります。
これはめんどくさいので、メモリ確保状態に関係なく呼出できるように改善しようとしてます。
今回の修正の第1目的は、メモリ確保前でもClear()できるようにする
だと思っています。
PRでは、既存の処理を if (メモリ確保後)
で括ることによってこれを実現しています。
これはこれで正しいように思っています。
しかし、ちょっと待ってください。
目的が メモリ確保前でもClear()できるようにする
なのに、なんで確保後かどうかを判定してるんでしたっけ?
386行目の前に確保前なら抜ける
を足してやればいいような気がします。
if (!m_pRawData || !m_nDataBufSize) {
assert(!nLength);
return;
}
※コードは動確しとりません。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
↑ 条件判定文は判定条件が逆になっていますが、内容的にはこの PR の最新のコードとほぼ同じです。
(m_nDataBufSize が int なので負の場合を考慮していないという点が違いますが)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
既存のコードを変更せずに追加になるので、提案の方法のほうが差分確認しやすいという面はありますが。
sakura_core/mem/CMemory.cpp
Outdated
m_nRawLen = nLength; | ||
assert(m_nRawLen <= m_nDataBufSize-2); | ||
m_pRawData[m_nRawLen ]=0; | ||
m_pRawData[m_nRawLen+1]=0; //終端'\0'を2つ付加する('\0''\0'==L'\0')。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(別件です。)
このコードの有効性に疑問があります。
引数nLengthに偶数を指定した場合には一定の意味があります。
ANSIバッファとして書き込んだバイナリ列をUNICODEバッファとして解釈したい場合、UNICODEのNULは2バイトなので2個目のNULを書く意味があります。
引数nLengthに基数を指定した場合にはやや微妙だと思います。
ANSIバッファは1バイトずつアクセスできますが、UNICODEバッファは2バイト単位でアクセスします。WORD境界のアラインメントを無視して2個目のNULを書く意味はありません。どうせやるなら3個目のNULの要否判断も組み込んで、有効データの後ろに1つ以上の(WORD)NULが含まれることを保証したほうがいいように思います。
あふぉ ← 6バイトのsjis文字列
↓ 半角カナに変換して _SetLength(3) する
アフォ␀␀ア ← 6バイトのsjis文字列
このPRのステータス。
個人的には 3. で構わないと思っています。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
対応ありがとうございます。
assertに付けたコメントは、このまま「追加」でよいと思っています。
「NULを2個付けるコードの有効性」に関する疑問は別途検証でよいような気がしています。
sakura-editor#780 でのCNativeW の初期状態での仕様を取り消して、 sakura-editor#948 の不具合を修正する
PR の目的
#780 でのCNativeW の初期状態での仕様を取り消して、 #948 の不具合を修正する
カテゴリ
PR の背景
#780 で #780 (comment) に対応した結果CNativeW の初期状態での仕様が変更になってしまった。
CNativeW の初期状態での仕様に依存したコードによって #948 の不具合が発生した。
PR のメリット
#948 の不具合を修正できる。
PR のデメリット (トレードオフとかあれば)
特になし
PR の影響範囲
CNativeW の初期状態でバッファが確保されていないことに依存したコード
関連チケット
#780
#948
参考資料
なし
変更手順