在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            新聞中心

            EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > 指針、結(jié)構(gòu)體、聯(lián)合體的安全規(guī)范

            指針、結(jié)構(gòu)體、聯(lián)合體的安全規(guī)范

            作者: 時間:2007-02-06 來源:網(wǎng)絡(luò) 收藏
            賦予了C編程最大的靈活性;體使得C程序整齊而緊湊;在某些要求注重效率的場合有精彩的表現(xiàn),這三個要素是C語言的精華。


            然而,精華并不意味著完美,
            C語言在賦予程序員足夠靈活性的同時,也給了程序員很多犯錯誤的機(jī)會。所以有必要關(guān)注、體和的實現(xiàn)細(xì)節(jié),從而保障程序的性。


            在此.第一部分介紹《
            MISRAC2004》中與相關(guān)的部分規(guī)則,第二部分講解體和的操作。下文中凡是未加特殊說明的都是強制(required)規(guī)則,個別推薦(advisory)規(guī)則加了“推薦”標(biāo)示。


            1
            指針的

            MISRAC2004》關(guān)于指針的主要分為三個部分:指針的類型轉(zhuǎn)換規(guī)則、指針運算的規(guī)則和指針的有效性規(guī)則。


            1.1
            指針的類型轉(zhuǎn)換

            指針類型轉(zhuǎn)換是個高風(fēng)險的操作,所以應(yīng)該盡量避免進(jìn)行這個操作。MISRAC對其中可能造成嚴(yán)重錯誤的情況作了嚴(yán)格的限定,選擇其中兩條作簡要分析。


            規(guī)則
            11.4(推薦):指向不同數(shù)據(jù)類型的指針之間不能相互轉(zhuǎn)換。

            思考如下程序:

            uint8_t*pl;

            uint32)_t*p2

            p2=(uint32_t*)pl;

            *注:uint8_t表示8位無符號整型,uint3_t表示32位無符號整型。*


            程序員希望將從
            p1單元開始的4個字節(jié)組成一個32付的整型來參與運算。


            如果
            CPU允許各種數(shù)據(jù)對象存放在任意的存儲單元,則以上轉(zhuǎn)換沒有問題。但某些CPU對某種()數(shù)據(jù)類型加強了對齊限制,要求這些數(shù)據(jù)對象占用一定的地址空間,比如某些字節(jié)尋址的CPU會要求32(4字節(jié))整型存放在4的整倍數(shù)地址上。在這個前提下.思考程序中的指針轉(zhuǎn)換:假設(shè)pl一開始指向的是0x00O3單元(uint8_t型的整型沒有對齊要求),則執(zhí)行最后一行強制轉(zhuǎn)換后,p2到底指向哪個單元就無法預(yù)料了。


            規(guī)則
            1 1.5:指針轉(zhuǎn)換過程中不允許丟失指針的constvolatile屬性。按如下定義指針:

            uIntl6t x;

            uint16_t*const cpi=x; *const指針*

            uintl6_t*const *pcpi; *指向const指針的指針*

            const uintl6_t* *ppci; *指向const整型指針的指針*

            uIntl6_t* *ppi ;

            const uint16_t *pci; *指向const整型的指針*

            volatik uint16_t *pvi; *指向volatile整型的指針*

            uintl6_t *pi;


            則以下指針轉(zhuǎn)換是允許的:

            pl=cpi;

            以下指針轉(zhuǎn)換是不允許的:

            pi=(umtl6_t*)pci;

            pi=(uintl6_t*)pvil

            ppi=(uintl6_t* *)pcpi;

            ppi=(uintl6_I**)ppci+


            以上非法指針類型轉(zhuǎn)換將會丟失
            const或者volatile類型。丟失const屬性,將有可能導(dǎo)致在對只讀內(nèi)容進(jìn)行寫操作時,編譯器不會發(fā)出警告,編譯器將不對具有volatile屬性的變量作優(yōu)化;丟失volatile屬性,編譯器的優(yōu)化可能導(dǎo)致程序員預(yù)先設(shè)計的硬件時序操作失效,這樣的錯誤很難發(fā)現(xiàn)。關(guān)于constvolatile關(guān)鍵字的詳細(xì)作用,讀者可參考ISOC獲取更多信息。


            1
            2 指針的運算

            ISOC標(biāo)準(zhǔn)中,對指向數(shù)組成員的指針運算(包括算術(shù)運算、比較等)做了規(guī)范定義,除此以外的指針運算屬于未定義(undefined)范圍,具體實現(xiàn)有賴于具體編譯器,其性無法得到保障,MISRAC中對指針運算的合法范圍做了如下限定。


            規(guī)則
            17.1:只有指向數(shù)組的指針才允許進(jìn)行算術(shù)運算①。

            規(guī)則17 2:只有指向同一個數(shù)組的兩個指針才允許相減 ②。

            規(guī)則17 3:只有指向同一個數(shù)組的兩個指針才允許用>,>=,=等關(guān)系運算符進(jìn)行比較。


            為了盡最大可能減少直接進(jìn)行指針運算帶來的隱患,尤其是程序動態(tài)運行時可能發(fā)生的數(shù)組越界等問題,
            MISRAC對指針運算作了更為嚴(yán)格的規(guī)定。規(guī)則17 4:只允許用數(shù)組索引做指針運算。按如下方式定義數(shù)組和指針:

            uint8_t a[10];

            uint8_t *p;


            *(p+5)=O是不允許的.而p[5]=O則是允許的,盡管就這段程序而言,二者等價。


            以下給出一段程序,讀者可參照相應(yīng)程序行的注釋,細(xì)細(xì)品味上述規(guī)則的含義。

            void my_fn(uInt*_t*p1uint8_t p2[]){


            ①其實此處的算術(shù)運算僅限定于指針加減某個整數(shù).比如
            ppoint=point5ppoint++等。0兩個指針可指向不同的散組成員。

            uint8_t index=0

            uint8_t *p3

            uint8_t *p4;

            *pl=O

            p1++; *不允許,pl不是指向數(shù)組的指針*

            p1=p1+5;*不允許,pl不是指向數(shù)組的指針*

            pl[5]=O; *不允許,p1不是指向數(shù)組的指針*

            p3=p1[5];*不允許,pl不是指向數(shù)組的指針*

            p2[0]=O;

            index++;

            index=index+5

            p2[index]=0 *允許*

            *(p2+index)=O; *不允許*

            p4=p2[5]; *允許*

            }


            1
            3
            指針的有效性

            下面介紹《MISRAC2004》中關(guān)于指針有效性的規(guī)則。


            規(guī)則
            17 6:動態(tài)分配對象的地址不允許在本對象消亡后傳給另外一個對象。


            這條規(guī)則的實際意義是不允許將棧對象的地址傳給外部作用域的對象。

            請看以下這段程序:

            #includestdi0h

            char*getm(void){

            char p[]=hello world″;

            return p;

            intmain(){

            char* str=NULL;

            str=getm();

            printf(str);


            程序員希望最后的輸出結(jié)果是″
            hello world″這個字符串,然而實際運行時,卻出現(xiàn)亂碼(具體內(nèi)容依賴于編譯環(huán)境)。


            簡單分析一下,由于chat p[]=hell0 world″這條語句是在棧中分配空間存儲″hell0 world″這個字符串,當(dāng)函數(shù)getm()返回的時候,已分配的空間將會被釋放(但內(nèi)容并不會被銷毀),而priM(str)涉及系統(tǒng)調(diào)用,有數(shù)據(jù)壓棧,會修改從前分配給數(shù)組p[]存儲空間的內(nèi)容,導(dǎo)致程序無法得到預(yù)期的效果。


            倘若將
            getm()函數(shù)體中的char p[]=hell0 world″程序行改成char*q=hello world″,則執(zhí)行main( )的時候可以正確輸出″hello world″,這是由于q指向的是靜態(tài)數(shù)據(jù)區(qū),而非棧中的某個單元。


            所以,數(shù)組名是指針不假,但在實現(xiàn)細(xì)節(jié)上還是有很大的差異,程序員在使用指針的時候必須慎之又慎。

             

            2 結(jié)構(gòu)體、聯(lián)合體的安全規(guī)范

            規(guī)則18 4:不允許使用聯(lián)合體。這是一個不太近情理的規(guī)定,在具體闡述為何《MISRAC2004》如此“痛恨”聯(lián)合體之前,首先需要明確與聯(lián)合體相關(guān)的細(xì)節(jié):

            ①聯(lián)合體的末尾有多少個填充單元?

            ②聯(lián)合體中的各個成員如何對齊?

            ③多字節(jié)的數(shù)據(jù)類型高低字節(jié)如何排放順序?

            ④如果包含位字段(bitfield),各位如何排放順序?


            針對細(xì)節(jié)3舉個例子。

            程序段21

            typedef union{

            uilat32_t word;

            uint8_t bytes[4];

            }word_msg_t;

            unit32_t read_nasg(void){

            word_rnsg_t tmp;

            *注:tmn bvte[O]對府干tmpword的高8位,tmp byter[l]對應(yīng)于

            tmp.WOfO的次高8位,依次類推。*

            tmpbytes[O]=read_byte()

            tmpbytes[1]=read_byte();

            tmpbytes[2]=read_byte()

            tmpbytes[3]=read_byte();

            retlarn(trapword);

            }

            以上代碼格式在各種通信協(xié)議中使用的頻率很高,接收端接收到的數(shù)據(jù)一般都以字節(jié)為單位存放,主控程序需要根據(jù)相應(yīng)的協(xié)議將接收到的多個字節(jié)進(jìn)行組合。為了實現(xiàn)相同的功能,《MISRA-C2004》推薦了read_msg()函數(shù)的另外一種寫法。

            程序段22

            uint32_trcad_msg(void){

            uint32_t word

            Word=((unit32_t)read_byte())24;

            word=word(((unit32_t)read_byte())16);

            word=word(((unit32_t)read_byted_byte8);

            word=word(((unit32_t)read_byte());

            return(word)

            }


            無論從程序的清晰程度還是執(zhí)行效率來講,程序段
            21都優(yōu)于程序段22。然而,程序段21Intel 80x86Pentlurn體系(1ittleendian,存儲多字節(jié)整數(shù)的時候低字節(jié)存放在低地址,高字節(jié)存放在高地址)CPU中和在Motorola 68K體系(bigendian,存儲多字節(jié)整數(shù)的時候高字節(jié)存放在低地址,低字節(jié)存放在高地址)cPu中的執(zhí)行結(jié)果完全不一樣。假設(shè)read_byte()函數(shù)返回的數(shù)據(jù)依次是0x01、0x020x030x04,則在Intel體系中,程序段21

            read_msg()函數(shù)的返回值是0x432l;在Motorola體系中,read_msg()的返回值是0x1234


            無論在
            Intel體系還是Motorola體系中,程序段22read_msg()的返回值都是0x1 234。


            以上是聯(lián)合體中多字節(jié)整型字節(jié)排放順序不定導(dǎo)致漏洞的一個例子。倘若不明確聯(lián)合體末尾填充的細(xì)節(jié),或者不清楚聯(lián)合體成員的對齊方式,或者不注意聯(lián)合體中位字段成員的位排列次序,都有可能導(dǎo)致錯誤。作為將安全性放在第一位的
            C標(biāo)準(zhǔn),MlSRAC禁止使用聯(lián)合體并非不可理喻。


            然而,聯(lián)合體畢竟是C語言的一個重要元素,所以MISRAC主張禁止使用聯(lián)合體的同時,也為效率和資源要求比較苛刻的情況開了一扇門,程序員在明確聯(lián)合體各個實現(xiàn)細(xì)節(jié)的前提下,在萬不得已的時候,仍可謹(jǐn)慎使用聯(lián)合體,在不同體系的CPU間移植程序的時候要注意做相應(yīng)的修改。


            此外,《
            MISRAC2004》中也對結(jié)構(gòu)體和聯(lián)合體的編程風(fēng)格作了限定。


            規(guī)則
            18 1:所有結(jié)構(gòu)體和聯(lián)合體的定義必須保證完整性。


            由于涉及
            ISOC中類型定義完整性等概念,礙于篇幅的原因,此處就不再贅述,讀者可以參閱《MISRA-C2004》一書和ISOC標(biāo)準(zhǔn)以了解更多信息,完善自己的編程風(fēng)格。

             

            3 結(jié)

            總而言之,對于C程序中最為靈活的指針、結(jié)構(gòu)體和聯(lián)合體,程序員不僅僅要關(guān)注其定義和操作的一般方法,更要注重實現(xiàn)的細(xì)節(jié)。由于指針、聯(lián)合體等的功能性錯誤一般都可以逃過編譯器的檢查,所以稍有疏忽,就可能導(dǎo)致程序在運行的時候出現(xiàn)嚴(yán)重錯誤,程序員必須以嚴(yán)謹(jǐn)甚至苛刻的態(tài)度對待指針、結(jié)構(gòu)體和聯(lián)合體。



            評論


            相關(guān)推薦

            技術(shù)專區(qū)

            關(guān)閉