40년 전의 소프트웨어 취약점 복구

6343 단어 excelhistorybugetl
주의: 나는 이 정확한 숫자를 가지고 있다. 왜냐하면 나는 처음에 버그를 발견한 날에 썼기 때문이다.
나는 3상 임상시험의 비용을 낮추기 위해 ETL 시스템을 개발하고 있었다.이렇게 하는 과정에서 나는 몇 가지 데이터를 읽고 36916개의 가능한 날짜를 처리했다.3만6천916명 중 2명은 검증하지 못했다.나는 이런 날짜가 대형 제약회사의 고객들로부터 왔기 때문에, 그들이 우리에게 제공한 전자 표는 왕왕 우리의 규격과 그다지 일치하지 않는다.당신보다 훨씬 큰 고객과 함께 일할 때, 당신은 보통 입을 헤벌리고 참기만 하고, 매일 그 안에서 조금씩 죽는다. (언젠가는 야후가 멸종한 IDIF 형식으로 나의 지옥을 써야 한다는 것을 일깨워 준다.)
그러나 그날 이 약물들은 나무랄 데가 없었다.원본 데이터를 검사할 때 실패한 날짜는 2011년 1월 1일과 2007년 1월 1일입니다.나는 그날들을 안다.이것은 고객이 제공한 경솔한 데이터가 아니다.내가 방금 쓴 소프트웨어에 버그가 하나 있는데, 이 버그는 1983년에 처음으로 발표된 것이다.
소프트웨어 생태계를 잘 모르는 누구에게도 신비롭게 들릴 수 있지만 일리가 있다.아주 오래 전에 다른 회사로 하여금 돈을 벌게 하는 결정을 내렸기 때문에, 나의 고객은 나에게 한 오류를 복구하는 데 돈을 지불할 때 손해를 보았다. 이 오류는 한 회사가 의외로 도입한 것이고, 다른 회사가 고의로 도입한 것이다.그러나 이 점을 설명하기 위해서 저는 세 번째 회사에 대해 이야기해야 합니다. 그것은 하나의 기능을 도입했고 결국은 하나의 버그가 되었고 다른 역사적 에피소드가 되었습니다. 그럼에도 불구하고 제가 그날 복원한 그 난해한 버그를 만들었습니다.

역사.


시스템 클록



과거 좋은 날, 애플 컴퓨터는 때때로 자동으로 날짜를 1904년 1월 1일로 리셋했다.이유는 간단하다.당시Apple computers used battery-powered "system clocks"에 날짜와 시간을 기록했다.배터리를 다 썼을 때 무슨 일이 일어났습니까?애플의 컴퓨터 추적 날짜는 the number of seconds since the epoch였다.이런 의미에서 anepoch은 단지 우리가 계산하기 시작한 참고 날짜일 뿐이다. Macintosh컴퓨터에 있어서 그 기원은 1904년 1월 1일이다. 시스템의 시계 배터리가 다 소모되었을 때 그것은 너의 새로운 날짜이다. 그것은 이상한 문제를 일으켰다.
당시 애플은 시작 날짜부터 계산된 초를 32비트(1과 0)로 저장했다.한 명은 두 값 중 하나인 0 또는 1을 저장할 수 있습니다.두 자리는 네 개의 값 중 하나인 00, 01, 10, 11을 저장할 수 있다.세 자리는 8개의 값 중 하나, 000, 001, 010, 011, 100, 101, 110, 111 등을 보존할 수 있다.32자리는 얼마나 수용할 수 있습니까?32비트는 232개 또는 4294967296개의 값 중 하나를 저장할 수 있습니다.232초가 136년을 딱 넘었다. 이것이 바로 왜 older Macs couldn't handle dates after 2040 시스템의 시계 배터리가 다 소모되면, 당신의 날짜는 기원 후의 0초로 재설정되고, 컴퓨터를 켤 때마다 수동으로 날짜를 재설정해야 한다. (또는 시스템 시계를 위해 새 배터리를 구매할 때까지).
그러나 애플이 날짜를 기원 후의 초수로 저장하는 해결 방안은 기원 전의 날짜를 처리할 수 없다는 것을 의미하며, 이는 심각한 영향을 미칠 것으로 보인다.이것은 애플이 내놓은 기능이지 버그가 아니다.다른 것 외에 Macintosh 운영체제가 Y2K 취약점에 영향을 받지 않는다는 뜻이다.(풍자적 의미를 가진 것은 많은 맥 응용 프로그램들이 맥의 제한을 극복하기 위해 자신의 날짜 시스템을 도입하기 때문에 피할 수 없다는 것이다.)

연꽃 1-2-3


계속 전진하자. 우리는 Lotus 1-2-3 IBM의 '킬러급 응용 프로그램' 이 개인용 컴퓨터 혁명을 가동시키는 데 도움을 주었다. 비록 VisiCalc 애플에서 진정으로 개인용 컴퓨터를 가동했지만.공평하게 1-2-3이 나오지 않으면 개인용 컴퓨터가 예전처럼 빠르게 발전하지 않을 수도 있고 컴퓨터 기술도 크게 달라질 수 있다.그러나 연꽃은 1-2-3을 잘못 1900년을 윤년이라고 부른다.(문학 용어로 이 말이 바로 우리가 말한'깔개')

마이크로소프트가 그들의 첫 번째 전자 표 프로그램인 멀티플랜 it didn't have much market penetration 을 발표했을 때따라서 Excel을 구상할 때, 그들은 1-2-3의 줄/열 명명 방안을 복제할 뿐만 아니라, 1900을 윤년a problem that remains to this day으로 보는 것을 포함하여 버그와 호환시키기로 결정했다.이것은 슬그머니 하기 위한 것이 아니다.Lotus 1-2-3 스프레드시트를 가져오려면 Excel이 필요합니다.따라서 1-2-3에서는 오류지만 Excel에서는 날짜 오류를 의미하는 경우도 있는 기능입니다.

역원


마이크로소프트가 애플의 Macintosh 컴퓨터를 위해 Excel을 발표하려고 할 때, 그들은 문제를 만났다.앞에서 말한 바와 같이 Macintosh는 1904년 1월 1일 이전의 날짜를 인정하지 않는다.그러나 Excel은 1900년 1월 1일을 기원으로 사용했다.따라서 Excel은 역원이 무엇인지, 그리고 내부에 저장된 역원과 관련된 날짜를 식별하기 위해 수정되었다.This Microsoft support article explains the problem fairly clearly . 이것은 나의 잘못을 야기시켰다.

내 벌레


나의 고객은 많은 고객의 전자 표를 받았다.이러한 스프레드시트는 Windows에서 작성될 수 있지만 Mac에서 작성될 수 있습니다.따라서 스프레드시트의'기원'날짜는 1900년 1월 1일 또는 1904년 1월 1일일 수 있습니다.어느 건지 어떻게 알았어요?네, Excel file format exposes this information. 하지만 제가 사용하는 해석기는 없습니다. 1900이나 1904를 기반으로 한 전자 표가 있는지 알고 싶습니다.나는 Excel의 이진 형식을 어떻게 읽는지 찾아내고 해상도 관리자에게 패치를 보낼 수 있는 데 많은 시간을 들일 수 있을 것 같았지만, 나는 고객을 위해 해야 할 다른 일이 많아서, 주어진 전자 표가 1900인지 1904인지 확인하기 위해 계발식 프로그램을 빨리 만들었다.이것은 매우 간단하다.
Excel에서 날짜는 1998년 7월 5일일 수 있지만, 그 형식은 '07-05-98' (쓸모없는 미국 시스템), 'Jul 5, 98', 'Jul 51998', '5-Jul-98' 또는 다른 쓸모없는 형식일 수 있다. (풍자적으로 말하자면, 나의 Excel 버전에서 제공하지 않은 격식은 표준 ISO 8601 형식) 이다.그러나 내부에서 1900년의 날짜 시스템에 대해 포맷되지 않은 값은'35981'이고 1904년의 시스템에 대해 포맷되지 않은 값은'34519'이다.따라서 포맷된 날짜에서 연도를 추출하기 위해 튼튼한 날짜 해상도를 사용하고 Excel 날짜 해상도에서 연도를 추출합니다.만약 그들이 4년 간격을 둔다면, 나는 내가 사용한 것이 1904년의 날짜 시스템이라는 것을 안다.
그럼 나는 왜 포맷 날짜를 직접 사용하지 않습니까?1998년 7월 5일의 격식이'98년 7월'일 수도 있기 때문에 나는 한 달 동안의 어느 날을 잃었다.우리는 많은 회사에서 전자 표를 얻었다. 그들은 다양한 방식으로 전자 표를 만들었다. 그들은 우리가 (이 예에서 나를 가리킨다) 이해할 수 있기를 바란다.어쨌든, Excel이 옳았어, 나도 이렇게 했어야 했어!
그때 39082가 내 꼬리를 찼다.Lotus 1-2-3이 어떻게 1900년을 윤년으로 여겼는지, 그리고 어떻게 Excel에 충실하게 복제되었는지 기억하십니까?1900을 토대로 하루를 늘렸기 때문에 날짜 계산 기능에 의존하는 많은 기능들이 하루를 닫기 쉽다.이는 39082일이 2011년 1월 1일(Mac 컴퓨터에서)일 수도 있고 2006년 12월 31일(Windows에서)일 수도 있다는 뜻이다.만약 나의 '연간 해상도' 가 포맷 값에서 2011을 추출한다면 다행이다.그러나 Excel 해석기가 1900년인지 1904일자 시스템인지 모르기 때문에 기본적으로 자주 사용하는 1900일자 시스템으로 2006년을 년도로 되돌려줍니다. 제 소프트웨어는 년도를 5년 간격으로 보고 오류가 발생하면 포맷되지 않은 값을 기록하고 되돌려줍니다.
이 문제를 해결하기 위해 다음과 같은 (위조 코드) 를 작성했습니다.
difference = formatted_year - parsed_year
if 0 == difference:
    assume 1900 date system
if 4 == difference:
    assume 1904 date system
if 5 == difference && 12 == month && 31 == day:
    assume 1904 date system
모든 36916개의 날짜가 정확하게 해석되었다.
그나저나 according to an anecdote from Joel Spolsky Lotus1-2-3 "bug"는 Lotus 소프트웨어를 간소화하려는 시도일 수 있습니다.

좋은 웹페이지 즐겨찾기